virtual iframe. IE + FireFox

本文介绍了一个使用JavaScript实现的IFrame调整大小及拖动功能的示例。该示例通过自定义的IFrameControl类实现了浏览器窗口内的元素拖拽与调整大小功能,并针对不同浏览器类型进行了兼容性处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    
<title>=IFrame= Test IE only</title>
<script type="text/javascript">
var IFrameControl = {
    _registerInstance:
function(frame){this.frameInstance=frame},
    _funMouseDragEnd:
function(){var _iframe = IFrameControl.getInstance();if(_iframe.Data.isDrag) IFrameControl.applyDrag(); IFrameControl.setDragStop();},
    _funMouseDragStart:
function(){var _iframe = IFrameControl.getInstance(); if(!_iframe.Data.isDrag) {IFrameControl.applyDrag(); return;} if ((IFrameControl.IsIE && window.event && window.event.button==1|| (!IFrameControl.IsIE && typeof(arguments[0])=="object" && arguments[0].button>=0)) {var now_x = window.event ? event.x : arguments[0].pageX; var alpdiv = document.getElementById(_iframe.Data.alphaSplit);if (alpdiv) {alpdiv.style.left = parseInt(alpdiv.style.left) + now_x - _iframe.Data.xBegin + "px";_iframe.Data.xBegin  = now_x;}}},
    IsIE:(document.all
!=undefined && document.all!=null),
    frameInstance:
null,
    getInstance:
function(argumentlist){return (argumentlist==null||argumentlist.length==0? this.frameInstance : argumentlist[0];},
    CreateInstance:
function(sidebar, splitbar){var _frame=new IFrame(sidebar, splitbar);IFrameControl._registerInstance(_frame);return _frame;},
    RegisterDragEvent:
function(startDragHandler, endDragHandler){if(window.attachEvent) {document.attachEvent("onmousemove", startDragHandler);document.attachEvent("onmouseup", endDragHandler);} else if (window.addEventListener) {window.addEventListener('mousemove', startDragHandler, false);window.addEventListener('mouseup', endDragHandler, false);}},
    UnRegisterDragEvent:
function(startDragHandler, endDragHandler){if (window.detachEvent) {document.detachEvent("onmousemove", startDragHandler);document.detachEvent("onmouseup", endDragHandler);} else if (window.removeEventListener) {window.removeEventListener('mousemove', startDragHandler, false);window.removeEventListener('mouseup', endDragHandler, false);}},
    reSize:
function() {var frame = IFrameControl.getInstance(); frame.sideElement.style.height = frame.rootElement.clientHeight - 5 + "px";},
    applyDrag:
function(){var frame = IFrameControl.getInstance(); var mask = document.getElementById(frame.Data.maskFrame); var alpdiv = document.getElementById(frame.Data.alphaSplit); if (mask) frame.documentBody.removeChild(mask); if (alpdiv) {var x_Left = parseInt(alpdiv.style.left) - parseInt(alpdiv.style.width) + 1; frame.sideElement.style.width = (x_Left > 0 ? x_Left : 0+ "px"; frame.documentBody.removeChild(alpdiv);} IFrameControl.UnRegisterDragEvent(IFrameControl._funMouseDragStart, IFrameControl._funMouseDragEnd);},
    setDragStop:
function(){var frame = IFrameControl.getInstance(); frame.Data.isDrag = falseif(IFrameControl.IsIE){frame.documentBody.createControlRange().select()}else{var ev = document.createEvent("Events");ev.initEvent("click"truefalse);frame.spliterBar.dispatchEvent(ev);/*frame.spliterBar.fireEvent("onclick");frame.spliterBar.setSelectionRange(0,0);*/}},

    setDragStart:
function()
    {
        
var frame    = IFrameControl.getInstance();
        
var alphaDiv = document.createElement("DIV");
        
var maskDiv  = document.createElement("DIV");
        alphaDiv.id                 
= frame.Data.alphaSplit;
        alphaDiv.style.top          
= frame.spliterBar.offsetTop + "px";
        alphaDiv.style.left         
= frame.spliterBar.offsetLeft + "px";
        alphaDiv.style.width        
= Math.max(frame.spliterWidth, frame.spliterBar.clientWidth) + "px";
        alphaDiv.style.height       
= frame.spliterBar.clientHeight + "px";
        alphaDiv.style.zIndex       
= frame.spliterBar.style.zIndex + 20;
        alphaDiv.style.position     
= "absolute";
        alphaDiv.style.cursor       
= "e-resize";
        alphaDiv.style.background   
= "#eeeeee";
        alphaDiv.style.borderLeft   
= "1px dashed #000000";
        alphaDiv.style.borderRight  
= "1px dashed #000000";
        frame.documentBody.appendChild(alphaDiv);

        maskDiv.id                  
= frame.Data.maskFrame;
        maskDiv.style.top           
= 0 + "px";
        maskDiv.style.left          
= 0 + "px";
        maskDiv.style.width         
= (frame.rootElement.clientWidth > frame.rootElement.scrollWidth) ? frame.rootElement.clientWidth : frame.rootElement.scrollWidth + "px";
        maskDiv.style.height        
= (frame.rootElement.clientHeight > frame.rootElement.scrollHeight) ? frame.rootElement.clientHeight : frame.rootElement.scrollHeight + "px";
        maskDiv.style.zIndex        
= frame.spliterBar.style.zIndex + 10;
        maskDiv.style.position      
= "absolute";
        maskDiv.style.background    
= "#ffffff";
        
if (IFrameControl.IsIE)
            maskDiv.style.filter    
= "progid:DXImageTransform.Microsoft.Alpha(opacity=30)";
        
else
            maskDiv.style.opacity   
= 0.3;
        frame.documentBody.appendChild(maskDiv);

        frame.Data.isDrag 
= true;
        frame.Data.xBegin 
= window.event ? event.x : arguments[0].pageX;
        IFrameControl.RegisterDragEvent(IFrameControl._funMouseDragStart, IFrameControl._funMouseDragEnd);
    }
};

function IFrame(sidebar, splitbar)
{
    
this.Data         = {isDrag:false,xBegin:0,alphaSplit:sidebar+"alphaDiv",maskFrame:"shield"};
    
this.spliterWidth = 5;
    
this.rootElement  = document.documentElement||document.body;
    
this.documentBody = document.body||document.documentElement;
    
this.sideElement  = document.getElementById(sidebar);
    
this.spliterBar   = document.getElementById(splitbar);

    
this.spliterBar.style.width      = this.spliterWidth + "px";
    
this.spliterBar.style.zIndex     = 100;
    
this.spliterBar.style.background = "#666666";
    
this.documentBody.style.margin   = 0 + "px";
    
this.documentBody.style.padding  = 0 + "px";
    
this.rootElement.style.overflow  = "hidden";

    
if(window.attachEvent)
    {
        
this.spliterBar.attachEvent("onmousemove"function(){IFrameControl.getInstance().spliterBar.style.cursor='e-resize'}); this.spliterBar.attachEvent("onmouseout",  function(){IFrameControl.getInstance().spliterBar.style.cursor='default'}); this.spliterBar.attachEvent("onmousedown", IFrameControl.setDragStart);
        window.attachEvent(
"onload", IFrameControl.reSize); window.attachEvent("onresize", IFrameControl.reSize);
    }
    
else if(window.addEventListener)
    {
        
this.spliterBar.addEventListener('mousemove'function(){IFrameControl.getInstance().spliterBar.style.cursor='e-resize'}, false); this.spliterBar.addEventListener('mouseout',  function(){IFrameControl.getInstance().spliterBar.style.cursor='default'}, false); this.spliterBar.addEventListener('mousedown', IFrameControl.setDragStart, false);
        window.addEventListener(
'load', IFrameControl.reSize, false); window.addEventListener('resize', IFrameControl.reSize, false);
    }
}
</script>

</head>
<body>
    
<table border="0" style="width:100%;">
        
<tr>
            
<td style="width:1px;"><div id="leftsidearea" style="width:200px; overflow:auto;"><div style="height:2000px;">asdf</div></div></td>
            
<td id="spliter"></td>
            
<td>
                
<pre>FireFox下有Bug. 拖动后部分UI被选择,第二次拖动时鼠标变形</pre>
                
<table id="table1" border="1"></table>
            
</td>
        
</tr>
    
</table>
</body>
<script type="text/javascript">
    IFrameControl.CreateInstance(
"leftsidearea""spliter");
</script>



<script type="text/javascript" language="javascript">
var DOM={Element:{},Input:{},Search:{}};
DOM.IsIE 
= (navigator.appName=="Microsoft Internet Explorer");

DOM.GetEvent 
= DOM.IsIE? function(base){return window.event;}:function(base){return (base.length>0&&base[0].constructor==Event)?base[0]:null;};
DOM.GetEventElement 
= function(base){var ev=DOM.GetEvent(base);if(ev==null)return nullreturn DOM.IsIE?ev.srcElement:ev.target;};
DOM.RegisterObjectEvent 
= function(obj,param){if(DOM.IsIE){obj.attachEvent("on"+param[0],param[1]);}else{obj.addEventListener(param[0], param[1], false);}};

DOM.Input.TextBox 
= {
    NewTextBox:
function(nameObj,hashAttr,value){var o=document.createElement("input");return o;},
    Validate2DateTime:
function(){var element=DOM.GetEventElement(arguments);if(element==null)return;alert(element.value);},
    Validate2Number:
function(fractionDigits){alert('Validate2Number');}
};

DOM.Search.MatchFirstWith 
= function(parent,matchHandler,param){var l=parent.childNodes.length;if(l>100)return null;for(var i=0;i<l;i++){if(matchHandler(param)){return parent.childNodes[i];}}}
DOM.Search.FindNodeByTagName 
= function(el, tag) {var l=el.childNodes.length; if(l>100){return null;}for(var i=0;i<l;i++){if(el.childNodes[i].tagName!=undefined && el.childNodes[i].tagName!=null && el.childNodes[i].tagName.toLowerCase()==tag.toLowerCase()){return el.childNodes[i];}}};
DOM.Search.FindNodeById 
= function(el, id) {var l=el.childNodes.length; if(l>100){return null;}for(var i=0;i<l;i++){var txtId=el.childNodes[i].getAttribute("id");if(txtId!=null&&el.childNodes[i].getAttribute("id").toLowerCase()==id.toLowerCase()){return el.childNodes[i];}}};

function TableBuilder(tableid)
{
    
this._DataArray     = null;
    
this._VirtualRoot   = null;
    
this.IsIE           = (navigator.appName=="Microsoft Internet Explorer");
    
this.Table          = document.getElementById(tableid);

    
if (this.Table == null) {throw tableid+" is not found!";}
    
if (this.Table.tBodies.length <= 0) {var tbody=document.createElement("tbody");this.Table.appendChild(tbody);this._VirtualRoot=tbody;} else {this._VirtualRoot=this.Table.tBodies.item(0);}
    
if (!this.IsIE) {this._VirtualRoot.insertRow = function(index){var tr=document.createElement("tr");if(index==undefined||index==null){this.appendChild(tr);}else{this.insertBefore(tr,this.childNodes[index]);}return tr;}}

    
this.RegisterTemplateCells = function(argumentsList) {this._DataArray=arguments;}
    
this.ModifierTemplateCell = function(index, handler, param) {if(this._DataArray==null||this._DataArray.length<=index)return;handler(this._DataArray[index],param);}
    
this.AppendTemplateCell = function(obj) {if(this._DataArray==null){this._DataArray=new Array();}this._DataArray[this._DataArray.length++]=obj;}

    
this.Locate = function(i,j) {if(arguments.length>=2){return this._VirtualRoot.childNodes[i].childNodes[j];}else if(arguments.length>=1){return this._VirtualRoot.childNodes[i]}else{this._VirtualRoot}}
    
this.CreateRow = function(index) {if(this._DataArray==null){throw "template undefined!";}var tr=(index==undefined||index==null)?this._VirtualRoot.insertRow():this._VirtualRoot.insertRow(index);if(tr==null){throw "create row failed!";}var l=this._DataArray.length;for(var i=0;i<l;i++){var td;if(this.IsIE){td=tr.insertCell()}else{td=document.createElement("td");tr.appendChild(td);};switch(typeof(this._DataArray[i])){case"object":td.appendChild(this._DataArray[i].cloneNode(true));break;case"string":td.innerHTML=this._DataArray[i];break;default:break;}}return tr;}
    
this.RemoveRow = function(index) {if(this.Table.rows.length<=index)return false;if(this.IsIE){this._VirtualRoot.deleteRow(index)}else{this._VirtualRoot.removeChild(this._VirtualRoot.childNodes[index])}}
}

var tbuilder = new TableBuilder("table1");
tbuilder.RegisterTemplateCells(
"asdfsd", DOM.Input.TextBox.NewTextBox(), "ddddd", document.createElement("select"));
tbuilder.ModifierTemplateCell(
1, DOM.RegisterObjectEvent, new Array("blur",DOM.Input.TextBox.Validate2DateTime));
tbuilder.CreateRow().cells[
0].innerHTML="123";
tbuilder.CreateRow().cells[
0].innerHTML="456";
tbuilder.CreateRow().cells[
0].innerHTML="789";
tbuilder.CreateRow(
1).cells[0].innerHTML="erwqqrwwer";
tbuilder.CreateRow(
1);
tbuilder.CreateRow(
1);
tbuilder.RemoveRow(
1);
tbuilder.Locate(
1).cells[1].innerHTML="<input type="button" onclick="alert('hehe');" />";
tbuilder.Locate(
1,2).innerHTML="ba ga 2.";
tbuilder.Locate(
2,1).setAttribute("id""input1");
DOM.Search.FindNodeByTagName(tbuilder.Locate(
2,1), "input").style.display="none";
DOM.Search.FindNodeById(tbuilder.Locate(
2,1), "input1");

//if (DOM.IsIE)
//
{
//
    document.getElementById("ssddff").attachEvent("onblur", DOM.Input.TextBox.Validate2DateTime);
//
}
//
else
//
{
//
    document.getElementById("ssddff").addEventListener("blur", DOM.Input.TextBox.Validate2DateTime, false);
//
}

</script>

</html>
 
在debian12上使用postfix和dovecot和数据库MarirDB搭建邮件系统的日志中测试发送邮件出现以下报错,怎样排除解决,结合Foxmail上报错误信息:554 5.5.1 Error: no valid recipients: 2025-08-13T11:19:37.123918+08:00 mail12 dovecot: auth-worker(1998): Debug: conn unix:auth-worker (pid=1997,uid=103): Disconnected: Connection closed (fd=-1) 2025-08-13T11:19:37.124762+08:00 mail12 dovecot: auth-worker(1998): Debug: mysql(localhost): Connection finished (queries=1, slow queries=0) 2025-08-13T11:21:17.483478+08:00 mail12 dovecot: auth: Debug: mysql(localhost): Connection finished (queries=0, slow queries=0) 2025-08-13T11:23:04.004018+08:00 mail12 postfix/smtpd[2006]: connect from unknown[192.168.5.197] 2025-08-13T11:23:04.006858+08:00 mail12 dovecot: auth: Debug: Loading modules from directory: /usr/lib/dovecot/modules/auth 2025-08-13T11:23:04.006930+08:00 mail12 dovecot: auth: Debug: Module loaded: /usr/lib/dovecot/modules/auth/lib20_auth_var_expand_crypt.so 2025-08-13T11:23:04.008243+08:00 mail12 dovecot: auth: Debug: Module loaded: /usr/lib/dovecot/modules/auth/libdriver_mysql.so 2025-08-13T11:23:04.008372+08:00 mail12 dovecot: auth: Debug: sqlpool(mysql): Creating new connection 2025-08-13T11:23:04.008496+08:00 mail12 dovecot: auth: Debug: Read auth token secret from /run/dovecot/auth-token-secret.dat 2025-08-13T11:23:04.009571+08:00 mail12 dovecot: auth: Debug: mysql(localhost): Connecting 2025-08-13T11:23:04.009960+08:00 mail12 dovecot: auth: Debug: auth client connected (pid=0) 2025-08-13T11:23:04.011840+08:00 mail12 dovecot: auth: Debug: client in: AUTH#0111#011LOGIN#011service=smtp#011nologin#011lip=192.168.5.131#011rip=192.168.5.197 2025-08-13T11:23:04.011885+08:00 mail12 dovecot: auth: Debug: client passdb out: CONT#0111#011VXNlcm5hbWU6 2025-08-13T11:23:04.012284+08:00 mail12 dovecot: auth: Debug: client in: CONT#0111#011dXNlcjFAZHN3aW50ZWMuY29t (previous base64 data may contain sensitive data) 2025-08-13T11:23:04.012346+08:00 mail12 dovecot: auth: Debug: client passdb out: CONT#0111#011UGFzc3dvcmQ6 2025-08-13T11:23:04.012548+08:00 mail12 dovecot: auth: Debug: client in: CONT#0111#011ZHN0MTIz (previous base64 data may contain sensitive data) 2025-08-13T11:23:04.012606+08:00 mail12 dovecot: auth: Debug: sql(user1@dswintec.com,192.168.5.197): Performing passdb lookup 2025-08-13T11:23:04.015831+08:00 mail12 dovecot: auth-worker(2009): Debug: Loading modules from directory: /usr/lib/dovecot/modules/auth 2025-08-13T11:23:04.015910+08:00 mail12 dovecot: auth-worker(2009): Debug: Module loaded: /usr/lib/dovecot/modules/auth/lib20_auth_var_expand_crypt.so 2025-08-13T11:23:04.017669+08:00 mail12 dovecot: auth-worker(2009): Debug: Module loaded: /usr/lib/dovecot/modules/auth/libdriver_mysql.so 2025-08-13T11:23:04.017736+08:00 mail12 dovecot: auth-worker(2009): Debug: sqlpool(mysql): Creating new connection 2025-08-13T11:23:04.018582+08:00 mail12 dovecot: auth-worker(2009): Debug: mysql(localhost): Connecting 2025-08-13T11:23:04.019936+08:00 mail12 dovecot: auth-worker(2009): Debug: conn unix:auth-worker (pid=2008,uid=103): Server accepted connection (fd=14) 2025-08-13T11:23:04.020010+08:00 mail12 dovecot: auth-worker(2009): Debug: conn unix:auth-worker (pid=2008,uid=103): Sending version handshake 2025-08-13T11:23:04.020046+08:00 mail12 dovecot: auth-worker(2009): Debug: conn unix:auth-worker (pid=2008,uid=103): auth-worker<1>: Handling PASSV request 2025-08-13T11:23:04.020070+08:00 mail12 dovecot: auth-worker(2009): Debug: conn unix:auth-worker (pid=2008,uid=103): auth-worker<1>: sql(user1@dswintec.com,192.168.5.197): Performing passdb lookup 2025-08-13T11:23:04.020249+08:00 mail12 dovecot: auth-worker(2009): Debug: conn unix:auth-worker (pid=2008,uid=103): auth-worker<1>: sql(user1@dswintec.com,192.168.5.197): query: SELECT username AS user,password FROM mailbox WHERE username = 'user1@dswintec.com' AND active='1' 2025-08-13T11:23:04.020612+08:00 mail12 dovecot: auth-worker(2009): Debug: mysql(localhost): Finished query 'SELECT username AS user,password FROM mailbox WHERE username = 'user1@dswintec.com' AND active='1'' in 0 msecs 2025-08-13T11:23:04.022596+08:00 mail12 dovecot: auth-worker(2009): Debug: conn unix:auth-worker (pid=2008,uid=103): auth-worker<1>: sql(user1@dswintec.com,192.168.5.197): Finished passdb lookup 2025-08-13T11:23:04.022674+08:00 mail12 dovecot: auth: Debug: sql(user1@dswintec.com,192.168.5.197): Finished passdb lookup 2025-08-13T11:23:04.022792+08:00 mail12 dovecot: auth: Debug: auth(user1@dswintec.com,192.168.5.197): Auth request finished 2025-08-13T11:23:04.022903+08:00 mail12 dovecot: auth: Debug: client passdb out: OK#0111#011user=user1@dswintec.com#011 2025-08-13T11:23:04.022925+08:00 mail12 dovecot: auth-worker(2009): Debug: conn unix:auth-worker (pid=2008,uid=103): auth-worker<1>: Finished 2025-08-13T11:23:04.033768+08:00 mail12 postfix/proxymap[2007]: warning: connect to mysql server 127.0.0.1: Unknown database 'mail' 2025-08-13T11:23:04.033900+08:00 mail12 postfix/smtpd[2006]: warning: proxy:mysql:/etc/postfix/mysql_cf/mysql_virtual_sender_login_maps.cf lookup error for "user1@dswintec.com" 2025-08-13T11:23:04.033962+08:00 mail12 postfix/smtpd[2006]: NOQUEUE: reject: RCPT from unknown[192.168.5.197]: 451 4.3.0 <user1@dswintec.com>: Temporary lookup failure; from=<user1@dswintec.com> to=<user1@dswintec.com> proto=ESMTP helo=<IT-03> 2025-08-13T11:23:04.035019+08:00 mail12 postfix/smtpd[2006]: disconnect from unknown[192.168.5.197] ehlo=1 auth=1 mail=1 rcpt=0/1 data=0/1 quit=1 commands=4/6
最新发布
08-14
<think>我们正在处理一个邮件发送错误554 5.5.1 "no valid recipients"。这个错误通常表示Postfix无法识别收件人地址,或者收件人地址在配置中被拒绝。我们将结合日志和Foxmail的错误信息进行排查。 根据引用[3]中提到的配置步骤,以及用户提供的错误信息,我们可以从以下几个方面进行排查: 1. 检查收件人地址的格式是否正确。 2. 检查Postfix的配置,特别是收件人限制和虚拟域配置。 3. 检查MariaDB中存储的收件人地址信息是否正确。 4. 检查Dovecot的认证配置是否影响了邮件发送。 由于用户使用了MariaDB,我们假设用户使用了虚拟用户(即用户信息存储在数据库中),因此需要检查数据库中的收件人地址是否存在以及域名的配置。 具体步骤: 步骤1:验证收件人地址格式 确保在发送邮件时,收件人地址的格式正确,例如:user@example.com。同时,检查该收件人地址是否存在于数据库中。 步骤2:检查Postfix的main.cf配置 查看/etc/postfix/main.cf文件,确认以下配置: - mydestination:这个参数指定了哪些域名是本地投递的(即不需要中继)。如果收件人的域名不在mydestination中,并且也不在virtual_mailbox_domains中(如果使用了虚拟邮箱),那么Postfix会认为这个收件人地址无效。 - virtual_mailbox_domains:如果使用虚拟邮箱,确保收件人的域名已经在这个参数中指定,或者通过MySQL表查询。 - virtual_mailbox_maps:这个参数指定了如何查询有效的邮箱地址。确保查询语句正确,并且能够返回正确的收件人地址。 例如,配置可能类似于: virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf 步骤3:检查MySQL查询配置文件 检查上述两个MySQL查询配置文件(mysql-virtual-mailbox-domains.cf和mysql-virtual-mailbox-maps.cf)中的SQL语句是否正确,以及数据库连接信息(用户名、密码、数据库名)是否正确。 例如,mysql-virtual-mailbox-domains.cf可能包含: user = mailuser password = mailuserpass dbname = mailserver query = SELECT domain FROM virtual_domains WHERE domain='%s' 而mysql-virtual-mailbox-maps.cf可能包含: user = mailuser password = mailuserpass dbname = mailserver query = SELECT email FROM virtual_users WHERE email='%s' 步骤4:测试MySQL查询 使用命令行工具测试上述查询是否能够返回正确的结果。例如,测试收件人域名的查询: mysql -u mailuser -p mailserver -e "SELECT domain FROM virtual_domains WHERE domain='example.com'" 测试收件人地址的查询: mysql -u mailuser -p mailserver -e "SELECT email FROM virtual_users WHERE email='user@example.com'" 如果查询不到,那么需要检查数据库中的记录是否存在。 步骤5:检查日志 查看Postfix的日志(通常位于/var/log/mail.log)以获取更详细的错误信息。搜索错误代码554或错误信息"no valid recipients"。 例如,日志中可能会出现类似这样的信息: NOQUEUE: reject: RCPT from unknown[IP地址]: 554 5.5.1 <user@example.com>: Recipient address rejected: User unknown in virtual mailbox table; from=<sender@example.com> to=<user@example.com> proto=ESMTP helo=<hostname> 这样的日志表明,收件人地址在虚拟邮箱表中不存在。 步骤6:检查Foxmail配置 确保在Foxmail中设置的SMTP服务器地址、端口和认证信息正确。特别是,确保认证的用户名(发件人地址)是存在的。 步骤7:测试Postfix的收件人验证 使用以下命令测试Postfix的收件人验证: postmap -q user@example.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf 如果返回收件人地址,则说明查询正确;否则,需要检查配置文件。 步骤8:检查Dovecot认证 虽然Dovecot主要用于接收邮件,但发邮件时SMTP认证通常也需要Dovecot的认证服务。确保在Postfix中启用了sasl认证,并且指向Dovecot的认证socket。检查/etc/postfix/main.cf中的smtpd_sasl_type和smtpd_sasl_path等设置。 但注意,这个错误(554 5.5.1)通常与收件人地址有关,而不是发件人认证问题。 总结: 根据以上步骤,重点检查收件人地址在数据库中的存在性以及Postfix的虚拟邮箱域和邮箱映射的配置。 如果上述步骤无法解决问题,请提供具体的日志片段,以便进一步分析。 根据引用[1][2][3][4]的配置经验,我们还可以参考以下通用配置: - 确保在数据库的virtual_domains表中添加了收件人的域名。 - 确保在virtual_users表中添加了收件人的邮箱地址。 另外,引用[3]中提到了禁用Dovecot的明文认证(disable_plaintext_auth = no)和关闭SSL(ssl = no)的配置,但这主要影响接收邮件时的认证。发送邮件时,如果使用了STARTTLS,可能需要检查SSL配置,但554错误通常与SSL无关。 最后,如果问题仍然存在,请检查防火墙设置,确保SMTP端口(25或587)是开放的,并且Postfix监听在正确的端口上。 希望这些步骤能帮助您解决问题。</think>### Debian 12 Postfix + Dovecot + MariaDB 邮件发送错误 554 "no valid recipients" 排查指南 此错误表示 Postfix 无法识别收件人地址的有效性。以下是系统级排查步骤,结合日志分析和配置修复: #### 1. **核心原因定位** - **错误本质**:`554 5.5.1` 表明 Postfix 的收件人验证失败,通常由以下原因导致: - 收件人域名未在 Postfix 配置中声明 - 虚拟邮箱映射查询失败(MariaDB 连接或查询错误) - 收件人地址在数据库中不存在 #### 2. **关键配置检查(Postfix)** ```bash sudo nano /etc/postfix/main.cf ``` - **检查域名配置**:确保收件人域名在以下参数中声明: ```ini # 物理域名(需包含收件人域名) mydestination = localhost.$mydomain, localhost # 虚拟域名(关键配置!) virtual_mailbox_domains = mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf ``` *若收件人域名未在 `virtual_mailbox_domains` 或 `mydestination` 中声明,则触发此错误。* - **验证邮箱映射**:检查邮箱地址查询配置: ```ini virtual_mailbox_maps = mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf ``` #### 3. **MariaDB 映射文件验证** - **邮箱域名映射文件**: ```bash sudo nano /etc/postfix/mysql-virtual-mailbox-domains.cf ``` 内容应包含有效的 SQL 查询(示例): ```ini user = mail_admin password = your_db_password dbname = mailserver query = SELECT domain FROM virtual_domains WHERE domain='%s' ``` **测试命令**: ```bash postmap -q yourdomain.com mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf # 应返回 "yourdomain.com" ``` - **邮箱地址映射文件**: ```bash sudo nano /etc/postfix/mysql-virtual-mailbox-maps.cf ``` 示例配置: ```ini query = SELECT email FROM virtual_users WHERE email='%s' ``` **测试命令**: ```bash postmap -q user@yourdomain.com mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf # 应返回完整邮箱地址 ``` #### 4. **数据库排查** - 登录 MariaDB 检查收件人是否存在: ```sql USE mailserver; SELECT * FROM virtual_domains WHERE domain='yourdomain.com'; SELECT * FROM virtual_users WHERE email='recipient@yourdomain.com'; ``` - **权限验证**: ```sql GRANT SELECT ON mailserver.* TO 'mail_admin'@'localhost' IDENTIFIED BY 'password'; FLUSH PRIVILEGES; ``` #### 5. **日志深度分析** ```bash sudo tail -f /var/log/mail.log ``` - **关键日志线索**: ``` NOQUEUE: reject: RCPT from unknown[x.x.x.x]: 554 5.5.1 <recipient@domain>: Recipient address rejected: User unknown in virtual mailbox table ``` 表明: - 域名未在 `virtual_mailbox_domains` 中注册 - 或邮箱地址在 `virtual_users` 表中不存在 #### 6. **Foxmail 端验证** - 检查发件人域名是否与服务器配置的域名一致 - 尝试发送到同一域内的其他用户(排除单个邮箱问题) #### 7. **配置修复与重载** ```bash sudo postfix check # 检查配置语法 sudo systemctl reload postfix dovecot sudo systemctl restart postfix ``` #### 8. **高级故障排除** - **强制收件人验证**: ```bash sudo postmap -q "recipient@domain" mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf ``` 若返回空值,检查: - MariaDB 服务状态 - 数据库连接密码是否更新 - 表字段名是否匹配(如 `email` vs `mail`) > **引用说明**:基于 Debian 邮件服务器配置实践[^3][^4],需确保虚拟域和邮箱映射的数据库查询路径正确,且收件人地址存在于数据库中。 --- ### 相关问题 1. 如何为 Postfix + MariaDB 配置虚拟邮箱域映射? 2. Dovecot 认证失败应如何排查? 3. 在 Debian 12 上如何调试 Postfix 的 SMTP 协议交互? 4. MariaDB 权限配置错误如何影响 Postfix 的收件人验证?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值