使用Python向IP地址发送邮件
我正在尝试通过一个Python脚本发送邮件。使用常规的收件人地址格式“user@domain.tld”时,一切都很顺利。但是当我尝试用“user@[IP-Address]”作为收件人时,所有的调试输出看起来都很好,发送邮件的方法也能正常工作,但邮件就是收不到。我是通过终端的dig命令获取到这个IP地址的。
这是我写的方法,它期望收件人作为参数(省略了一些不重要的内容,并且隐藏了真实的地址和凭证)
def sendmail(receiver):
msg = MIMEText('This is the body of the mail.')
msg['From'] = email.utils.formataddr(('me', myaddr))
msg['To'] = email.utils.formataddr(('me', receiver))
msg['Subject'] = "Python Mail Script"
server = smtplib.SMTP(smtpServer, smtpPort)
try:
server.set_debuglevel(True)
# identify ourselves, prompting server for supported features
server.ehlo()
# If we can encrypt this session, do it
if server.has_extn('STARTTLS'):
server.starttls()
server.ehlo() # re-identify ourselves over TLS connection
server.login("me@...", "...")
server.sendmail("me@...", toAddr, msg.as_string())
finally:
server.quit()
我发送给IP地址的消息输出是这样的(同样,我隐藏了smtp服务器和邮件/IP地址):
send: 'ehlo [127.0.1.1]\r\n'
reply: '250-mail.example.de\r\n'
reply: '250-PIPELINING\r\n'
reply: '250-SIZE 102400000\r\n'
reply: '250-VRFY\r\n'
reply: '250-ETRN\r\n'
reply: '250-STARTTLS\r\n'
reply: '250-AUTH PLAIN LOGIN\r\n'
reply: '250-AUTH=PLAIN LOGIN\r\n'
reply: '250-ENHANCEDSTATUSCODES\r\n'
reply: '250-8BITMIME\r\n'
reply: '250 DSN\r\n'
reply: retcode (250); Msg: mail.example.de
PIPELINING
SIZE 102400000
VRFY
ETRN
STARTTLS
AUTH PLAIN LOGIN
AUTH=PLAIN LOGIN
ENHANCEDSTATUSCODES
8BITMIME
DSN
send: 'STARTTLS\r\n'
reply: '220 2.0.0 Ready to start TLS\r\n'
reply: retcode (220); Msg: 2.0.0 Ready to start TLS
send: 'ehlo [127.0.1.1]\r\n'
reply: '250-mail.example.de\r\n'
reply: '250-PIPELINING\r\n'
reply: '250-SIZE 102400000\r\n'
reply: '250-VRFY\r\n'
reply: '250-ETRN\r\n'
reply: '250-AUTH PLAIN LOGIN\r\n'
reply: '250-AUTH=PLAIN LOGIN\r\n'
reply: '250-ENHANCEDSTATUSCODES\r\n'
reply: '250-8BITMIME\r\n'
reply: '250 DSN\r\n'
reply: retcode (250); Msg: mail.example.de
PIPELINING
SIZE 102400000
VRFY
ETRN
AUTH PLAIN LOGIN
AUTH=PLAIN LOGIN
ENHANCEDSTATUSCODES
8BITMIME
DSN
send: 'AUTH PLAIN AHRob21hc0B0b3Jh6feldi5kZQBiYWdpbmVy\r\n'
reply: '235 2.7.0 Authentication successful\r\n'
reply: retcode (235); Msg: 2.7.0 Authentication successful
send: 'mail FROM:<me@example.de> size=234\r\n'
reply: '250 2.1.0 Ok\r\n'
reply: retcode (250); Msg: 2.1.0 Ok
send: 'rcpt TO:<me@[IP-ADDRESS]>\r\n'
reply: '250 2.1.5 Ok\r\n'
reply: retcode (250); Msg: 2.1.5 Ok
send: 'data\r\n'
reply: '354 End data with <CR><LF>.<CR><LF>\r\n'
reply: retcode (354); Msg: End data with <CR><LF>.<CR><LF>
data: (354, 'End data with <CR><LF>.<CR><LF>')
send: 'Content-Type: text/plain; charset="us-ascii"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: 7bit\r\nFrom: me <me@example.de>\r\nTo: me <me@[IP-ADDRESS]>\r\nSubject: Python Mail Script\r\n\r\nThis is the body of the mail.\r\n.\r\n'
reply: '250 2.0.0 Ok: queued as 4C5A78560196\r\n'
reply: retcode (250); Msg: 2.0.0 Ok: queued as 4C5A78560196
data: (250, '2.0.0 Ok: queued as 4C5A78560196')
send: 'quit\r\n'
reply: '221 2.0.0 Bye\r\n'
reply: retcode (221); Msg: 2.0.0 Bye
有人看到什么错误或问题吗?
补充:我在大学里使用自己的smtp postfix服务器(不幸的是无法访问外部网络),发送邮件到这个服务器的“user@[IP-ADDRESS]”时,邮件是能收到的。这可能是另一个迹象,说明在上面提到的有问题的情况下,接收方的smtp服务器根本不允许使用IP地址作为目标。
补充2:/var/log/mail.log
mail.log:Sep 9 00:34:06 mail postfix/qmgr[4854]: A30168560199: from=<me@example.de>, size=1197, nrcpt=1 (queue active)
mail.log:Sep 9 00:34:06 mail postfix/smtp[19355]: A30168560199: to=<me@[IP-ADDRESS]>, relay=none, delay=314, delays=313/0.04/0.01/0, dsn=4.4.1, status=deferred (connect to IP-ADDRESS[IP-ADDRESS]:25: Connection refused)
mail.log:Sep 9 00:38:31 mail postfix/smtpd[19907]: warning: Illegal address syntax from my_host_where_the_python_script_runs[IP of me] in RCPT command: <me@IP-ADDRESS>
所以我使用的SMTP服务器与接收方服务器的连接被拒绝,4分钟后,smtp守护进程说它收到了错误的语法,尽管在我通过脚本发送的握手中显示“250 Ok”...所以基本上我认为接收方的SMTP拒绝了这个请求。谢谢大家。
1 个回答
电子邮件地址中的域名就像网站的域名一样——一个服务器通常会在一个IP地址上处理多个不同的域名。所以在这种情况下,你需要在请求中提供具体的名称。例如,一个位于 1.2.3.4
的邮件服务器可能同时服务于 abc.com
和 xyz.com
。如果你发送 RCPT TO: <joe@[1.2.3.4]>
,服务器就不知道你是想联系 joe@abc.com
还是 joe@xyz.com
。服务器可能随便选择一个(可能选择错了),接受这个邮件然后把它丢掉,或者直接拒绝这个邮件。
除非你已经和服务器的运营者确认过,确保服务器会把发给 user@[ip]
的邮件送到你期望的域名,否则你不能指望它会这样做。