【问题标题】:Sending mail from Python using SMTP使用 SMTP 从 Python 发送邮件
【发布时间】:2010-09-09 00:49:43
【问题描述】:

我正在使用以下方法通过 SMTP 从 Python 发送邮件。这是正确的使用方法还是我遗漏了一些问题?

from smtplib import SMTP
import datetime

debuglevel = 0

smtp = SMTP()
smtp.set_debuglevel(debuglevel)
smtp.connect('YOUR.MAIL.SERVER', 26)
smtp.login('USERNAME@DOMAIN', 'PASSWORD')

from_addr = "John Doe <john@doe.net>"
to_addr = "foo@bar.com"

subj = "hello"
date = datetime.datetime.now().strftime( "%d/%m/%Y %H:%M" )

message_text = "Hello\nThis is a mail from your server\n\nBye\n"

msg = "From: %s\nTo: %s\nSubject: %s\nDate: %s\n\n%s" 
        % ( from_addr, to_addr, subj, date, message_text )

smtp.sendmail(from_addr, to_addr, msg)
smtp.quit()

【问题讨论】:

标签: python smtp


【解决方案1】:

我使用的脚本非常相似;我在这里发布它作为如何使用 email.* 模块生成 MIME 消息的示例;所以这个脚本可以很容易地修改为附加图片等。

我依靠我的 ISP 添加日期时间标头。

我的 ISP 要求我使用安全的 smtp 连接来发送邮件,我依赖 smtplib 模块(可在 http://www1.cs.columbia.edu/~db2501/ssmtplib.py 下载)

与您的脚本一样,用于在 SMTP 服务器上进行身份验证的用户名和密码(下面给出虚拟值)在源代码中以纯文本形式显示。这是一个安全漏洞;但最好的选择取决于您需要(想要?)保护这些。

========================================

#! /usr/local/bin/python


SMTPserver = 'smtp.att.yahoo.com'
sender =     'me@my_email_domain.net'
destination = ['recipient@her_email_domain.com']

USERNAME = "USER_NAME_FOR_INTERNET_SERVICE_PROVIDER"
PASSWORD = "PASSWORD_INTERNET_SERVICE_PROVIDER"

# typical values for text_subtype are plain, html, xml
text_subtype = 'plain'


content="""\
Test message
"""

subject="Sent from Python"

import sys
import os
import re

from smtplib import SMTP_SSL as SMTP       # this invokes the secure SMTP protocol (port 465, uses SSL)
# from smtplib import SMTP                  # use this for standard SMTP protocol   (port 25, no encryption)

# old version
# from email.MIMEText import MIMEText
from email.mime.text import MIMEText

try:
    msg = MIMEText(content, text_subtype)
    msg['Subject']=       subject
    msg['From']   = sender # some SMTP servers will do this automatically, not all

    conn = SMTP(SMTPserver)
    conn.set_debuglevel(False)
    conn.login(USERNAME, PASSWORD)
    try:
        conn.sendmail(sender, destination, msg.as_string())
    finally:
        conn.quit()

except:
    sys.exit( "mail failed; %s" % "CUSTOM_ERROR" ) # give an error message

【讨论】:

  • @Vincent:邮件失败; 'module' 对象没有属性 'SSLFakeSocket' - 使用 Gmail :(
  • 这听起来像是版本或导入问题,以帮助追踪它:您运行的是哪个版本的 Python? -- 您是否需要通过 SSL 连接到您的 SMTP 服务器(如果需要,您是否需要导入 ssmtplib,如上所述)?你可以直接从 python 交互导入 smtplib,如果可以,是否定义了 smtplib.SSLFakeSocket 类?希望我能帮忙
  • 使用 smtplib.SMTP_SSL(Python 最新版本中的标准)来创建连接,而不是 ssmtplib.STMP_SSL(上面提到的第三方模块)。请注意,标准模块以单个“s”开头。这对我有用。
  • from ssmtplib import SMTP_SSL as SMTP 替换为from smtplib import SMTP_SSL as SMTP,此示例可在标准Python 库中运行。
  • 添加msg['To'] = ','.join(destination),否则在gmail中看不到目的地
【解决方案2】:

我常用的方法...没有太大区别,但有点

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText

msg = MIMEMultipart()
msg['From'] = 'me@gmail.com'
msg['To'] = 'you@gmail.com'
msg['Subject'] = 'simple email in python'
message = 'here is the email'
msg.attach(MIMEText(message))

mailserver = smtplib.SMTP('smtp.gmail.com',587)
# identify ourselves to smtp gmail client
mailserver.ehlo()
# secure our email with tls encryption
mailserver.starttls()
# re-identify ourselves as an encrypted connection
mailserver.ehlo()
mailserver.login('me@gmail.com', 'mypassword')

mailserver.sendmail('me@gmail.com','you@gmail.com',msg.as_string())

mailserver.quit()

就是这样

【讨论】:

  • 如果您使用两步验证,您必须先创建一个应用专用密码,然后用它替换您的正常密码。见Sign in using App Passwords
  • 我同意,这是最好的答案,应该被接受。真正被接受的是劣等的。
  • 对于python3,使用:from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText
【解决方案3】:

此外,如果您想使用 TLS 而不是 SSL 进行 smtp 身份验证,那么您只需更改端口(使用 587)并执行 smtp.starttls()。这对我有用:

...
smtp.connect('YOUR.MAIL.SERVER', 587)
smtp.ehlo()
smtp.starttls()
smtp.ehlo()
smtp.login('USERNAME@DOMAIN', 'PASSWORD')
...

【讨论】:

    【解决方案4】:

    确保您没有任何防火墙阻止 SMTP。我第一次尝试发送电子邮件时,它被 Windows 防火墙和 McAfee 阻止 - 花了很长时间才找到它们。

    【讨论】:

      【解决方案5】:

      这个呢?

      import smtplib
      
      SERVER = "localhost"
      
      FROM = "sender@example.com"
      TO = ["user@example.com"] # must be a list
      
      SUBJECT = "Hello!"
      
      TEXT = "This message was sent with Python's smtplib."
      
      # Prepare actual message
      
      message = """\
      From: %s
      To: %s
      Subject: %s
      
      %s
      """ % (FROM, ", ".join(TO), SUBJECT, TEXT)
      
      # Send the mail
      
      server = smtplib.SMTP(SERVER)
      server.sendmail(FROM, TO, message)
      server.quit()
      

      【讨论】:

        【解决方案6】:

        我看到的主要问题是您没有处理任何错误:.login().sendmail() 都有可以抛出的documented exceptions,似乎.connect() 必须有某种方式来表明它无法连接 - 可能是底层套接字代码引发的异常。

        【讨论】:

          【解决方案7】:

          以下代码对我来说工作正常:

          import smtplib
          
          to = 'mkyong2002@yahoo.com'
          gmail_user = 'mkyong2002@gmail.com'
          gmail_pwd = 'yourpassword'
          smtpserver = smtplib.SMTP("smtp.gmail.com",587)
          smtpserver.ehlo()
          smtpserver.starttls()
          smtpserver.ehlo() # extra characters to permit edit
          smtpserver.login(gmail_user, gmail_pwd)
          header = 'To:' + to + '\n' + 'From: ' + gmail_user + '\n' + 'Subject:testing \n'
          print header
          msg = header + '\n this is test msg from mkyong.com \n\n'
          smtpserver.sendmail(gmail_user, to, msg)
          print 'done!'
          smtpserver.quit()
          

          参考:http://www.mkyong.com/python/how-do-send-email-in-python-via-smtplib/

          【讨论】:

          • Flask 有一个邮件框架:从 flask.ext.mail 导入邮件。我正在对其进行故障排除,并认为我会回到 Python 代码,看看我是否可以得到一些工作。我喜欢这个答案,因为它是赤裸裸的。哦,是的,它奏效了!
          • 注意: 上一版本的答案中包含:smtpserver.close() 必须是:smtpserver.quit(),因为close() 不会正确终止 TLS 连接! close() 将在 quit() 期间被调用。
          • 嗨,我在运行上述命令时遇到问题。当我使用 smtpserver.starttls() 时,我收到一个 SMTP 错误“SMTPServerDisconnected:连接意外关闭:[Errno 10054]”.. 报告在stackoverflow.com/questions/46094175/…
          【解决方案8】:

          我使用 SMTP 发送邮件的示例代码。

          import smtplib, ssl
          
          smtp_server = "smtp.gmail.com"
          port = 587  # For starttls
          sender_email = "sender@email"
          receiver_email = "receiver@email"
          password = "<your password here>"
          message = """ Subject: Hi there
          
          This message is sent from Python."""
          
          
          # Create a secure SSL context
          context = ssl.create_default_context()
          
          # Try to log in to server and send email
          server = smtplib.SMTP(smtp_server,port)
          
          try:
              server.ehlo() # Can be omitted
              server.starttls(context=context) # Secure the connection
              server.ehlo() # Can be omitted
              server.login(sender_email, password)
              server.sendmail(sender_email, receiver_email, message)
          except Exception as e:
              # Print any error messages to stdout
              print(e)
          finally:
              server.quit()
          

          【讨论】:

            【解决方案9】:

            您应该确保以正确的格式格式化日期 - RFC2822

            【讨论】:

              【解决方案10】:

              看到所有这些冗长的答案了吗?请允许我通过几行代码来进行自我宣传。

              导入和连接:

              import yagmail
              yag = yagmail.SMTP('john@doe.net', host = 'YOUR.MAIL.SERVER', port = 26)
              

              那么它只是一个单行:

              yag.send('foo@bar.com', 'hello', 'Hello\nThis is a mail from your server\n\nBye\n')
              

              当它超出范围时它实际上会关闭(或者可以手动关闭)。此外,它将允许您在密钥环中注册您的用户名,这样您就不必在脚本中写出您的密码(在写 yagmail 之前真的很困扰我!)

              有关包/安装、提示和技巧,请查看gitpip,适用于 Python 2 和 3。

              【讨论】:

              • @PascalvKoolen 我安装了 yagmail,并尝试通过提供我的电子邮件 ID 和密码进行连接。但它给了我一个身份验证错误
              【解决方案11】:

              基于this example我做了以下函数:

              import smtplib
              from email.mime.multipart import MIMEMultipart
              from email.mime.text import MIMEText
              
              def send_email(host, port, user, pwd, recipients, subject, body, html=None, from_=None):
                  """ copied and adapted from
                      https://stackoverflow.com/questions/10147455/how-to-send-an-email-with-gmail-as-provider-using-python#12424439
                  returns None if all ok, but if problem then returns exception object
                  """
              
                  PORT_LIST = (25, 587, 465)
              
                  FROM = from_ if from_ else user 
                  TO = recipients if isinstance(recipients, (list, tuple)) else [recipients]
                  SUBJECT = subject
                  TEXT = body.encode("utf8") if isinstance(body, unicode) else body
                  HTML = html.encode("utf8") if isinstance(html, unicode) else html
              
                  if not html:
                      # Prepare actual message
                      message = """From: %s\nTo: %s\nSubject: %s\n\n%s
                      """ % (FROM, ", ".join(TO), SUBJECT, TEXT)
                  else:
                              # https://stackoverflow.com/questions/882712/sending-html-email-using-python#882770
                      msg = MIMEMultipart('alternative')
                      msg['Subject'] = SUBJECT
                      msg['From'] = FROM
                      msg['To'] = ", ".join(TO)
              
                      # Record the MIME types of both parts - text/plain and text/html.
                      # utf-8 -> https://stackoverflow.com/questions/5910104/python-how-to-send-utf-8-e-mail#5910530
                      part1 = MIMEText(TEXT, 'plain', "utf-8")
                      part2 = MIMEText(HTML, 'html', "utf-8")
              
                      # Attach parts into message container.
                      # According to RFC 2046, the last part of a multipart message, in this case
                      # the HTML message, is best and preferred.
                      msg.attach(part1)
                      msg.attach(part2)
              
                      message = msg.as_string()
              
              
                  try:
                      if port not in PORT_LIST: 
                          raise Exception("Port %s not one of %s" % (port, PORT_LIST))
              
                      if port in (465,):
                          server = smtplib.SMTP_SSL(host, port)
                      else:
                          server = smtplib.SMTP(host, port)
              
                      # optional
                      server.ehlo()
              
                      if port in (587,): 
                          server.starttls()
              
                      server.login(user, pwd)
                      server.sendmail(FROM, TO, message)
                      server.close()
                      # logger.info("SENT_EMAIL to %s: %s" % (recipients, subject))
                  except Exception, ex:
                      return ex
              
                  return None
              

              如果您只传递body,则将发送纯文本邮件,但如果您将html 参数与body 参数一起传递,则将发送html 电子邮件(对于不这样做的电子邮件客户端,回退到文本内容) t 支持 html/mime 类型)。

              示例用法:

              ex = send_email(
                    host        = 'smtp.gmail.com'
                 #, port        = 465 # OK
                  , port        = 587  #OK
                  , user        = "xxx@gmail.com"
                  , pwd         = "xxx"
                  , from_       = 'xxx@gmail.com'
                  , recipients  = ['yyy@gmail.com']
                  , subject     = "Test from python"
                  , body        = "Test from python - body"
                  )
              if ex: 
                  print("Mail sending failed: %s" % ex)
              else:
                  print("OK - mail sent"
              

              顺便说一句。如果您想使用 gmail 作为测试或生产 SMTP 服务器, 启用对安全性较低的应用的临时或永久访问权限:

              【讨论】:

                【解决方案12】:

                或者

                import smtplib
                 
                from email.message import EmailMessage
                from getpass import getpass
                
                
                password = getpass()
                
                message = EmailMessage()
                message.set_content('Message content here')
                message['Subject'] = 'Your subject here'
                message['From'] = "USERNAME@DOMAIN"
                message['To'] = "you@mail.com"
                
                try:
                    smtp_server = None
                    smtp_server = smtplib.SMTP("YOUR.MAIL.SERVER", 587)
                    smtp_server.ehlo()
                    smtp_server.starttls()
                    smtp_server.ehlo()
                    smtp_server.login("USERNAME@DOMAIN", password)
                    smtp_server.send_message(message)
                except Exception as e:
                    print("Error: ", str(e))
                finally:
                    if smtp_server is not None:
                        smtp_server.quit()
                

                如果您想使用端口 465,您必须创建一个 SMTP_SSL 对象。

                【讨论】:

                  【解决方案13】:

                  你可以这样做

                  import smtplib
                  from email.mime.text import MIMEText
                  from email.header import Header
                  
                  
                  server = smtplib.SMTP('mail.servername.com', 25)
                  server.ehlo()
                  server.starttls()
                  
                  server.login('username', 'password')
                  from = 'me@servername.com'
                  to = 'mygfriend@servername.com'
                  body = 'That A Message For My Girl Friend For tell Him If We will go to eat Something This Nigth'
                  subject = 'Invite to A Diner'
                  msg = MIMEText(body,'plain','utf-8')
                  msg['Subject'] = Header(subject, 'utf-8')
                  msg['From'] = Header(from, 'utf-8')
                  msg['To'] = Header(to, 'utf-8')
                  message = msg.as_string()
                  server.sendmail(from, to, message)
                  

                  【讨论】:

                    【解决方案14】:

                    这是 Python 3.x 的一个工作示例

                    #!/usr/bin/env python3
                    
                    from email.message import EmailMessage
                    from getpass import getpass
                    from smtplib import SMTP_SSL
                    from sys import exit
                    
                    smtp_server = 'smtp.gmail.com'
                    username = 'your_email_address@gmail.com'
                    password = getpass('Enter Gmail password: ')
                    
                    sender = 'your_email_address@gmail.com'
                    destination = 'recipient_email_address@gmail.com'
                    subject = 'Sent from Python 3.x'
                    content = 'Hello! This was sent to you via Python 3.x!'
                    
                    # Create a text/plain message
                    msg = EmailMessage()
                    msg.set_content(content)
                    
                    msg['Subject'] = subject
                    msg['From'] = sender
                    msg['To'] = destination
                    
                    try:
                        s = SMTP_SSL(smtp_server)
                        s.login(username, password)
                        try:
                            s.send_message(msg)
                        finally:
                            s.quit()
                    
                    except Exception as E:
                        exit('Mail failed: {}'.format(str(E)))
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 2012-08-17
                      • 1970-01-01
                      • 1970-01-01
                      • 2015-06-22
                      • 1970-01-01
                      • 2016-01-13
                      • 2010-12-06
                      • 2017-06-26
                      相关资源
                      最近更新 更多