Python 2+smtplib跨网络环境发送邮件失败问题求助
嘿,我来帮你搞定这个头疼的问题!你的脚本在自己环境能跑,换了网络/IP就失效,大概率是异常被宽泛捕获但没暴露具体原因,再加上一些网络或配置细节没处理好。咱们一步步来修复:
1. 先把异常信息打出来——找到问题根源
你现在的except:太宽泛了,不管出什么错都只显示“Something went wrong...”,根本不知道是网络不通、账号验证失败还是格式错误。先把异常捕获改得具体点,这样能看到真正的问题:
import smtplib import traceback # 导入模块打印详细错误栈 gmail_user = 'name@gmail.com' gmail_password = 'password' sent_from = gmail_user to = ['me@gmail.com'] # 改成列表格式,避免字符串join出错 subject = 'OMG Super Important Message' score = 32 # 示例变量 body = 'Your score is %s! This is a message.' % score # 插入变量的方式 email_text = """\ From: %s To: %s Subject: %s %s """ % (sent_from, ", ".join(to), subject, body) try: # 换成TLS端口587(很多网络会拦截465的SSL端口) server = smtplib.SMTP('smtp.gmail.com', 587) server.ehlo() server.starttls() # 启用加密连接 server.ehlo() server.login(gmail_user, gmail_password) server.sendmail(sent_from, to, email_text) server.close() print 'Email sent!' except Exception, e: # Python2的异常捕获语法 print 'Something went wrong...' print 'Error details:', str(e) traceback.print_exc() # 打印详细错误栈,方便精准排查
2. 修复收件人格式的隐藏bug
你原代码里to = 'me@gmail.com'是字符串,", ".join(to)会把字符串拆成单个字符拼接(比如变成m, e, @, g, m, a, i, l, ., c, o, m),这会导致邮件服务器直接拒收收件人!一定要把to改成列表格式,比如to = ['me@gmail.com']或者to = ['me@gmail.com', 'another@xxx.com']。
3. 适配不同网络的端口设置
很多公司/公共网络会拦截465端口(SMTP_SSL),换成587端口(STARTTLS)成功率更高——上面的代码已经帮你改成了587端口的写法,这是解决网络拦截最常见的办法。
4. 检查Gmail账号的安全设置
如果对方的Gmail账号开启了两步验证(2FA),直接用原密码登录会失败,必须生成**应用专用密码(App Password)**来代替原密码;如果没开2FA,需要确保账号开启了“允许不太安全的应用访问”(不过Google现在对新账号默认关闭,建议直接用App Password更安全)。
5. 变量插入的优化(可选)
如果你觉得%s的写法不够直观,Python2也支持str.format()来插入变量,可读性更好:
score = 32 body = 'Your score is {score}! This is a message.'.format(score=score) # 或者更简洁的(Python2.7+支持) body = 'Your score is {}! This is a message.'.format(score)
让对方运行修改后的脚本,根据打印的错误信息就能精准定位问题了——比如如果是“Connection refused”就是网络端口被拦,如果是“Authentication failed”就是账号密码/安全设置的问题。
内容的提问来源于stack exchange,提问作者Moe

