【问题标题】:How to send an email with Python?如何使用 Python 发送电子邮件?
【发布时间】:2023-02-06 10:34:43
【问题描述】:

这段代码可以正常工作并给我发一封电子邮件:

import smtplib
#SERVER = "localhost"

FROM = 'monty@python.com'

TO = ["jon@mycompany.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('myserver')
server.sendmail(FROM, TO, message)
server.quit()

但是,如果我尝试将其包装在这样的函数中:

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    import smtplib
    """this is some test documentation in the function"""
    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()

并称之为我收到以下错误:

 Traceback (most recent call last):
  File "C:/Python31/mailtest1.py", line 8, in <module>
    sendmail.sendMail(sender,recipients,subject,body,server)
  File "C:/Python31\sendmail.py", line 13, in sendMail
    server.sendmail(FROM, TO, message)
  File "C:\Python31\lib\smtplib.py", line 720, in sendmail
    self.rset()
  File "C:\Python31\lib\smtplib.py", line 444, in rset
    return self.docmd("rset")
  File "C:\Python31\lib\smtplib.py", line 368, in docmd
    return self.getreply()
  File "C:\Python31\lib\smtplib.py", line 345, in getreply
    raise SMTPServerDisconnected("Connection unexpectedly closed")
smtplib.SMTPServerDisconnected: Connection unexpectedly closed

谁能帮我理解为什么?

【问题讨论】:

  • 你怎么调用这个函数?
  • 您发布的缩进与文件中的缩进相同吗?
  • @g.d.d.c 不,我确保正确缩进,这就是我粘贴它的方式。
  • 我通过将函数导入我的主模块并将我定义的参数传递给它来调用该函数。
  • 尽管@Arrieta 建议使用电子邮件包是解决此问题的最佳方法,但您的方法可行。您的两个版本之间的差异在字符串中:(1) 正如@NickODell 指出的那样,函数版本中有前导空格。标头不应有前导空格(除非它们被换行)。 (2) 除非 TEXT 包含一个前导空行,否则您将丢失标题和正文之间的分隔符。

标签: python email function smtplib


【解决方案1】:

我建议您一起使用标准包email和smtplib来发送电子邮件。请看下面的例子(转载自Python documentation)。请注意,如果您采用这种方法,“简单”任务确实很简单,而更复杂的任务(如附加二进制对象或发送普通/HTML 多部分消息)可以非常快速地完成。

# Import smtplib for the actual sending function
import smtplib

# Import the email modules we'll need
from email.mime.text import MIMEText

# Open a plain text file for reading.  For this example, assume that
# the text file contains only ASCII characters.
with open(textfile, 'rb') as fp:
    # Create a text/plain message
    msg = MIMEText(fp.read())

# me == the sender's email address
# you == the recipient's email address
msg['Subject'] = 'The contents of %s' % textfile
msg['From'] = me
msg['To'] = you

# Send the message via our own SMTP server, but don't include the
# envelope header.
s = smtplib.SMTP('localhost')
s.sendmail(me, [you], msg.as_string())
s.quit()

发送邮件到多个目的地,你也可以按照Python documentation中的例子:

# Import smtplib for the actual sending function
import smtplib

# Here are the email package modules we'll need
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart

# Create the container (outer) email message.
msg = MIMEMultipart()
msg['Subject'] = 'Our family reunion'
# me == the sender's email address
# family = the list of all recipients' email addresses
msg['From'] = me
msg['To'] = ', '.join(family)
msg.preamble = 'Our family reunion'

# Assume we know that the image files are all in PNG format
for file in pngfiles:
    # Open the files in binary mode.  Let the MIMEImage class automatically
    # guess the specific image type.
    with open(file, 'rb') as fp:
        img = MIMEImage(fp.read())
    msg.attach(img)

# Send the email via our own SMTP server.
s = smtplib.SMTP('localhost')
s.sendmail(me, family, msg.as_string())
s.quit()

如您所见,MIMEText 对象中的标头To 必须是由逗号分隔的电子邮件地址组成的字符串。另一方面,sendmail 函数的第二个参数必须是一个字符串列表(每个字符串都是一个电子邮件地址)。

因此,如果您有三个电子邮件地址:person1@example.com、person2@example.com和person3@example.com,您可以执行以下操作(省略明显部分):

to = ["person1@example.com", "person2@example.com", "person3@example.com"]
msg['To'] = ",".join(to)
s.sendmail(me, to, msg.as_string())

",".join(to) 部分从列表中生成单个字符串,以逗号分隔。

从你的问题中我了解到你还没有通过the Python tutorial——如果你想在 Python 中取得任何进展,这是必须的——文档对于标准库来说非常好。

【讨论】:

  • 谢谢,这在一个函数中非常有效,但是我怎样才能发送给多个收件人呢?由于 msg[to] 看起来像是一个字典键,我尝试用分号分隔 msg[to] 但这似乎不起作用。
  • @cloud311 与代码中的完全一样。它需要一个用逗号分隔的字符串:", ".join(["a@example.com", "b@example.net"])
  • 另请注意,To: 标头与信封收件人具有不同的语义。例如,您可以使用“Tony Meyer”<tony.meyer@gmail.com>'作为 To: 标头中的地址,但信封收件人只能是“tony.meyer@gmail.com”。要构建一个“好的”收件人:地址,请使用 email.utils.formataddr,例如 email.utils.formataddr("Tony Meyer", "tony.meyer@gmail.com")。
  • 小改进:应该使用with:with open(textfile, 'rb') as fp:打开文件。可以删除显式关闭,因为即使文件内部发生错误,with 块也会关闭文件。
  • 不特定于此答案,但是当连接到您无法控制的任何 SMTP 服务器时,您应该考虑它无法访问、速度慢、拒绝连接或其他任何情况的可能性。在代码方面你会得到一个异常,但是你需要找到一种方法来稍后重试发送。如果您与自己的 sendmail/postfix 通话,那么它会为您处理重新发送。
【解决方案2】:

当我需要用 Python 发送邮件时,我会使用 mailgun API,这让我在发送邮件时遇到了很多麻烦。他们有一个很棒的应用程序/API,可以让您每月发送 5,000 封免费电子邮件。

发送电子邮件将是这样的:

def send_simple_message():
    return requests.post(
        "https://api.mailgun.net/v3/YOUR_DOMAIN_NAME/messages",
        auth=("api", "YOUR_API_KEY"),
        data={"from": "Excited User <mailgun@YOUR_DOMAIN_NAME>",
              "to": ["bar@example.com", "YOU@YOUR_DOMAIN_NAME"],
              "subject": "Hello",
              "text": "Testing some Mailgun awesomness!"})

您还可以跟踪事件等等,请参阅the quickstart guide。

【讨论】:

  • @PascalvKooten 关注你不断的 yagmail 广告绝对有趣(是的,先生,我下次会考虑,先生;)。但我发现几乎没有人关心 OP 问题,而是提出许多不同的解决方案,这让我感到非常困惑。就好像我在问如何更换我的 2009 smart 的灯泡,答案是:买一辆真正的梅赛德斯......
  • 太好了,我的任务对某些人有一定的娱乐价值。
  • @flaschbier 没有人关心 OP 问题的原因是因为标题是错误的。 “如何用 Python 发送电子邮件?”这是人们在单击该问题时来看的真正原因,他们希望yagmail 可以提供一个答案:漂亮而简短。给你。更多 yagmail 广告。
  • @PascalvKooten 没有冒犯。我假设您的任务是在 Python 中提供更好的电子邮件支持,我喜欢这样。如果我上次发现 yagmail 我必须实现邮件通知,我绝对会考虑它(麻省理工学院许可证和安装第 3 方软件在那个环境中是可能的)。关于问题的标题,我认为你是完全正确的。为什么不建议修改?
  • 只是说对于 Mailgun 客户来说,通过网络服务发送邮件比通过 SMTP 发送邮件更节省带宽(尤其是在使用任何附件的情况下)。
【解决方案3】:

我想通过建议 yagmail 包来帮助您发送电子邮件(我是维护者,抱歉打广告,但我觉得它真的很有帮助!)。

你的整个代码是:

import yagmail
yag = yagmail.SMTP(FROM, 'pass')
yag.send(TO, SUBJECT, TEXT)

请注意,我为所有参数提供了默认值,例如,如果你想发送给自己,你可以省略TO,如果你不想要主题,你也可以省略它。

此外,目标还在于使附加 html 代码或图像(和其他文件)变得非常容易。

在放置内容的地方,您可以执行以下操作:

contents = ['Body text, and here is an embedded image:', 'http://somedomain/image.png',
            'You can also find an audio file attached.', '/local/path/song.mp3']

哇,发送附件是多么容易啊!如果没有 yagmail,这将需要 20 行;)

此外,如果您设置一次,您将永远不必再次输入密码(并将其安全存储)。在您的情况下,您可以执行以下操作:

import yagmail
yagmail.SMTP().send(contents = contents)

哪个更简洁!

我邀请您查看github 或直接使用pip install yagmail 安装它。

【讨论】:

  • 除了 gmail,我可以使用 yagmail 吗?我正在尝试用于我自己的 SMTP 服务器。
  • @dtgq 感谢您的关注。就个人而言,我看不到攻击向量。如果有人要更改你要发送的路径下的文件,那么你有没有Attachment类也没关系;还是一样。如果他们可以更改您的代码,那么他们无论如何都可以做任何他们想做的事情(有/没有 root,这与 w.r.t. 电子邮件发送相同)。在我看来,这就像典型的“它很方便/神奇,所以它一定不太安全”。我很好奇你看到了什么真正的威胁?
  • 这只适用于 gmail 用户,也就是这对于几乎所有专业用途来说都是完全无用的。
【解决方案4】:

这是一个关于 Python 的例子3.x,比2.x简单多了:

import smtplib
from email.message import EmailMessage
def send_mail(to_email, subject, message, server='smtp.example.cn',
              from_email='xx@example.com'):
    # import smtplib
    msg = EmailMessage()
    msg['Subject'] = subject
    msg['From'] = from_email
    msg['To'] = ', '.join(to_email)
    msg.set_content(message)
    print(msg)
    server = smtplib.SMTP(server)
    server.set_debuglevel(1)
    server.login(from_email, 'password')  # user & password
    server.send_message(msg)
    server.quit()
    print('successfully sent the mail.')

调用此函数:

send_mail(to_email=['12345@qq.com', '12345@126.com'],
          subject='hello', message='Your analysis has done!')

以下可能仅适用于中国用户:

If you use 126/163, 网易邮箱, you need to set"客户端授权密码", like below:

参考:https://stackoverflow.com/a/41470149/2803344 https://docs.python.org/3/library/email.examples.html#email-examples

【讨论】:

  • 未来读者请注意:还有一个 SMTP_SSL 类和一个可能需要设置的 port 关键字参数。如果服务器需要 SSL,未加密的版本就会挂起。
【解决方案5】:

有缩进问题。下面的代码将起作用:

import textwrap

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    import smtplib
    """this is some test documentation in the function"""
    message = textwrap.dedent("""
        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()

【讨论】:

  • @geotheory 传递给函数的 SERVER 变量是用户凭据。
  • 不建议使用简单的字符串插值手动拼凑有效的 SMTP 消息,并且您的答案有一个错误完美地说明了这一点。 (正文需要以空行开头才能成为有效消息。)对于涉及 1980 年代纯文本以外的字符集的任何内容 7 位纯英语 US-ASCII(附件、国际化和其他 MIME 支持)你真的想使用处理这些东西的库。 Python email 库在这方面做得相当好(特别是从 3.6 开始),尽管它仍然需要对您正在做的事情有一些了解。
【解决方案6】:

在函数中缩进代码时(没问题),您还缩进了原始消息字符串的行。但是前导空格意味着标题行的折叠(连接),如RFC 2822 - Internet Message Format的第 2.2.3 和 3.2.3 节所述:

每个标题字段在逻辑上是一行字符,包括 字段名称、冒号和字段主体。为了方便 但是,为了处理每行 998/78 个字符的限制, 头字段的字段主体部分可以拆分成多个 线表示;这称为“折叠”。

在 sendmail 调用的函数形式中,所有行都以空格开头,因此“展开”(连接)并且您正在尝试发送

From: monty@python.com    To: jon@mycompany.com    Subject: Hello!    This message was sent with Python's smtplib.

除了我们的想法之外,smtplib 将不再理解 To: 和 Subject: 标头,因为这些名称仅在一行的开头被识别。相反,smtplib 将假定一个很长的发件人电子邮件地址:

monty@python.com    To: jon@mycompany.com    Subject: Hello!    This message was sent with Python's smtplib.

这是行不通的,因此您的异常也会出现。

解决方案很简单:只需保留之前的 message 字符串即可。这可以通过一个函数(如 Zeeshan 建议的那样)或直接在源代码中完成:

import smtplib

def sendMail(FROM,TO,SUBJECT,TEXT,SERVER):
    """this is some test documentation in the function"""
    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()

现在展开没有发生,你发送

From: monty@python.com
To: jon@mycompany.com
Subject: Hello!

This message was sent with Python's smtplib.

这是有效的,你的旧代码做了什么。

请注意,我还保留了标头和正文之间的空行以适应 the RFC 的第 3.5 节(这是必需的),并根据 Python 样式指南PEP-0008(这是可选的)将 include 放在函数之外。

【讨论】:

  • 注意:这篇文章的价值之一是对 SMTP 协议如何工作的细致入微的解释。
【解决方案7】:

确保您已授予发件人和收件人在电子邮件帐户中发送和接收来自未知来源(外部来源)的电子邮件的权限。

import smtplib

#Ports 465 and 587 are intended for email client to email server communication - sending email
server = smtplib.SMTP('smtp.gmail.com', 587)

#starttls() is a way to take an existing insecure connection and upgrade it to a secure connection using SSL/TLS.
server.starttls()

#Next, log in to the server
server.login("#email", "#password")

msg = "Hello! This Message was sent by the help of Python"

#Send the mail
server.sendmail("#Sender", "#Reciever", msg)

【讨论】:

【解决方案8】:

它可能会在您的消息中添加标签。在将消息传递给 sendMail 之前打印出消息。

【讨论】:

    【解决方案9】:

    值得注意的是,SMTP 模块支持上下文管理器,因此无需手动调用 quit(),这将保证即使出现异常也会始终调用它。

        with smtplib.SMTP_SSL('smtp.gmail.com', 465) as server:
            server.ehlo()
            server.login(user, password)
            server.sendmail(from, to, body)
    

    【讨论】:

      【解决方案10】:

      我对发送电子邮件的软件包选项不满意,因此我决定制作并开源我自己的电子邮件发件人。它易于使用并且能够处理高级用例。

      安装:

      pip install redmail
      

      用法:

      from redmail import EmailSender
      email = EmailSender(
          host="<SMTP HOST ADDRESS>",
          port=<PORT NUMBER>,
      )
      
      email.send(
          sender="me@example.com",
          receivers=["you@example.com"],
          subject="An example email",
          text="Hi, this is text body.",
          html="<h1>Hi,</h1><p>this is HTML body</p>"
      )
      

      如果您的服务器需要用户名和密码,只需将user_name 和password 传递给EmailSender。

      我在 send 方法中包含了很多功能:

      • 包括附件
      • 将图像直接包含到 HTML 正文中
      • Jinja 模板
      • 开箱即用的更漂亮的 HTML 表格

      文档: https://red-mail.readthedocs.io/en/latest/

      源代码:https://github.com/Miksus/red-mail

      【讨论】:

      • 最终的赢家。热的!!
      【解决方案11】:

      因为我刚刚弄清楚这是如何工作的,所以我想我会把我的两个位放在这里。

      看来您没有在 SERVER 连接设置中指定端口,这在我尝试连接到未使用默认端口的 SMTP 服务器时对我产生了一些影响:25。

      根据 smtplib.SMTP 文档,您的 ehlo 或 helo 请求/响应应该自动处理,因此您不必担心这一点(但如果其他所有方法都失败,可能需要确认)。

      另一件要问自己的事情是,您是否允许在您的 SMTP 服务器上建立 SMTP 连接?对于 GMAIL 和 ZOHO 等网站,您必须实际进入并激活电子邮件帐户中的 IMAP 连接。您的邮件服务器可能不允许不是来自“本地主机”的 SMTP 连接?需要调查的事情。

      最后一件事是您可能想尝试在 TLS 上启动连接。大多数服务器现在都需要这种类型的身份验证。

      您会看到我在电子邮件中插入了两个 TO 字段。 msg['TO'] 和 msg['FROM'] msg 字典项允许正确的信息显示在电子邮件本身的标题中,人们会在收件人/发件人字段中看到电子邮件的接收端(您甚至可以在这里添加一个回复字段。TO 和 FROM 字段本身就是服务器所需要的。我知道我听说过一些电子邮件服务器拒绝电子邮件,如果他们没有适当的电子邮件标题。

      这是我在函数中使用的代码,它适用于我使用本地计算机和远程 SMTP 服务器(如图所示的 ZOHO)通过电子邮件发送 *.txt 文件的内容:

      def emailResults(folder, filename):
      
          # body of the message
          doc = folder + filename + '.txt'
          with open(doc, 'r') as readText:
              msg = MIMEText(readText.read())
      
          # headers
          TO = 'to_user@domain.com'
          msg['To'] = TO
          FROM = 'from_user@domain.com'
          msg['From'] = FROM
          msg['Subject'] = 'email subject |' + filename
      
          # SMTP
          send = smtplib.SMTP('smtp.zoho.com', 587)
          send.starttls()
          send.login('from_user@domain.com', 'password')
          send.sendmail(FROM, TO, msg.as_string())
          send.quit()
      

      【讨论】:

        【解决方案12】:

        另一个使用 gmail 的实现让我们说:

        import smtplib
        
        def send_email(email_address: str, subject: str, body: str):
        """
        send_email sends an email to the email address specified in the
        argument.
        
        Parameters
        ----------
        email_address: email address of the recipient
        subject: subject of the email
        body: body of the email
        """
        
        server = smtplib.SMTP('smtp.gmail.com', 587)
        server.starttls()
        server.login("email_address", "password")
        server.sendmail("email_address", email_address,
                        "Subject: {}
        
        {}".format(subject, body))
        server.quit()
        

        【讨论】:

          【解决方案13】:

          我写了一个简单的函数send_email(),用于使用smtplib和email包发送电子邮件(链接到我的article)。它还使用dotenv包来加载发件人电子邮件和密码(请不要在代码中保密!)。我使用 Gmail 作为电子邮件服务。密码是App Password(这里是Google docs如何生成App Password)。

          import os
          import smtplib
          from email.message import EmailMessage
          from dotenv import load_dotenv
          _ = load_dotenv()
          
          
          def send_email(to, subject, message):
              try:
                  email_address = os.environ.get("EMAIL_ADDRESS")
                  email_password = os.environ.get("EMAIL_PASSWORD")
          
                  if email_address is None or email_password is None:
                      # no email address or password
                      # something is not configured properly
                      print("Did you set email address and password correctly?")
                      return False
          
                  # create email
                  msg = EmailMessage()
                  msg['Subject'] = subject
                  msg['From'] = email_address
                  msg['To'] = to
                  msg.set_content(message)
          
                  # send email
                  with smtplib.SMTP_SSL('smtp.gmail.com', 465) as smtp:
                      smtp.login(email_address, email_password)
                      smtp.send_message(msg)
                  return True
              except Exception as e:
                  print("Problem during send email")
                  print(str(e))
              return False
          
          

          上面的方法对于简单的邮件发送是可以的。如果您正在寻找更高级的功能,例如 HTML 内容或附件 - 当然可以手动编码,但我建议使用现有的包,例如 yagmail。

          Gmail 每天有 500 封电子邮件的限制。要每天发送大量电子邮件,请考虑交易电子邮件服务提供商,如 Amazon SES、MailGun、MailJet 或 SendGrid。

          【讨论】:

            【解决方案14】:
            import smtplib
            
            s = smtplib.SMTP(your smtp server, smtp port) #SMTP session
            
            message = "Hii!!!"
            
            s.sendmail("sender", "Receiver", message) # sending the mail
            
            s.quit() # terminating the session
            

            【讨论】:

            • 如果您解释了您提供的代码如何回答问题,这将是一个更好的答案。
            【解决方案15】:

            只是为了补充答案,以便您的邮件传递系统可以扩展。

            我建议使用发件人的电子邮件配置、密码和收件人的配置文件(可以是 .json、.yml、.ini 等)。

            这样您就可以根据需要创建不同的可定制项目。

            下面是一个包含 3 个文件的小示例,config、functions 和 main。纯文本邮寄。

            config_email.ini

            [email_1]
            sender = test@test.com
            password = XXXXXXXXXXX
            recipients= ["email_2@test.com", "email_2@test.com"]
            
            [email_2]
            sender = test_2@test.com
            password = XXXXXXXXXXX
            recipients= ["email_2@test.com", "email_2@test.com", "email_3@test.com"]
            

            这些项目将从main.py,这将返回它们各自的值。

            具有功能的文件functions_email.py:

            import smtplib,configparser,json
            from email.mime.multipart import MIMEMultipart
            from email.mime.text import MIMEText
            
            def get_credentials(item):
                parse = configparser.ConfigParser()
                parse.read('config_email.ini')
                sender = parse[item]['sender ']
                password = parse[item]['password']
                recipients= json.loads(parse[item]['recipients'])
                return sender,password,recipients
            
            def get_msg(sender,recipients,subject,mail_body):
                msg = MIMEMultipart()
                msg['Subject'] = subject
                msg['From'] = sender 
                msg['To'] = ', '.join(recipients)       
                text = """
                """+mail_body+""" """
                part1 = MIMEText(text, "plain")
                msg.attach(part1)
                return msg
            
            def send_email(msg,sender,password,recipients):
                s = smtplib.SMTP('smtp.test.com')
                s.login(sender,password)
                s.sendmail(sender, recipients, msg.as_string())
                s.quit()    
            

            文件main.py:

            from functions_email import *
            
            sender,password,recipients = get_credenciales('email_2')
            subject= 'text to subject'
            mail_body = 'body....................'
            msg = get_msg(sender,recipients ,subject,mail_body)    
            send_email(msg,sender,password,recipients)
            

            此致!

            【讨论】:

              【解决方案16】:
              import smtplib, ssl
              
              port = 587  # For starttls
              smtp_server = "smtp.office365.com"
              sender_email = "170111018@student.mit.edu.tr"
              receiver_email = "professordave@hotmail.com"
              password = "12345678"
              message = """
              Subject: Final exam
              
              Teacher when is the final exam?"""
              
              def SendMailf():
                  context = ssl.create_default_context()
                  with smtplib.SMTP(smtp_server, port) as server:
                      server.ehlo()  # Can be omitted
                      server.starttls(context=context)
                      server.ehlo()  # Can be omitted
                      server.login(sender_email, password)
                      server.sendmail(sender_email, receiver_email, message)
                      print("mail send")
              

              【讨论】:

                【解决方案17】:

                在大量摆弄示例之后,例如here 这现在对我有用:

                import smtplib
                from email.mime.text import MIMEText
                
                # SMTP sendmail server mail relay
                host = 'mail.server.com'
                port = 587 # starttls not SSL 465 e.g gmail, port 25 blocked by most ISPs & AWS
                sender_email = 'name@server.com'
                recipient_email = 'name@domain.com'
                password = 'YourSMTPServerAuthenticationPass'
                subject = "Server - "
                body = "Message from server"
                
                def sendemail(host, port, sender_email, recipient_email, password, subject, body):
                    try:
                        p1 = f'<p><HR><BR>{recipient_email}<BR>'
                        p2 = f'<h2><font color="green">{subject}</font></h2>'
                        p3 = f'<p>{body}'
                        p4 = f'<p>Kind Regards,<BR><BR>{sender_email}<BR><HR>'
                        
                        message = MIMEText((p1+p2+p3+p4), 'html')  
                        # servers may not accept non RFC 5321 / RFC 5322 / compliant TXT & HTML typos
                
                        message['From'] = f'Sender Name <{sender_email}>'
                        message['To'] = f'Receiver Name <{recipient_email}>'
                        message['Cc'] = f'Receiver2 Name <>'
                        message['Subject'] = f'{subject}'
                        msg = message.as_string()
                
                        server = smtplib.SMTP(host, port)
                        print("Connection Status: Connected")
                        server.set_debuglevel(1)
                        server.ehlo()
                        server.starttls()
                        server.ehlo()
                        server.login(sender_email, password)
                        print("Connection Status: Logged in")
                        server.sendmail(sender_email, recipient_email, msg)
                        print("Status: Email as HTML successfully sent")
                
                    except Exception as e:
                            print(e)
                            print("Error: unable to send email")
                
                # Run
                sendemail(host, port, sender_email, recipient_email, password, subject, body)
                print("Status: Exit")
                

                【讨论】:

                  【解决方案18】:

                  就您的代码而言,它似乎没有任何根本性的错误,只是不清楚您实际上是如何调用该函数的。我能想到的是,当您的服务器没有响应时,您将收到此 SMTPServerDisconnected 错误。如果您在 smtplib(下面的摘录)中查找 getreply() 函数,您就会明白。

                  def getreply(self):
                      """Get a reply from the server.
                  
                      Returns a tuple consisting of:
                  
                        - server response code (e.g. '250', or such, if all goes well)
                          Note: returns -1 if it can't read response code.
                  
                        - server response string corresponding to response code (multiline
                          responses are converted to a single, multiline string).
                  
                      Raises SMTPServerDisconnected if end-of-file is reached.
                      """
                  

                  查看 https://github.com/rreddy80/sendEmails/blob/master/sendEmailAttachments.py 上的示例,如果您正在尝试这样做(DRY 方法),它也使用函数调用来发送电子邮件。

                  【讨论】:

                    猜你喜欢
                    • 2023-02-22
                    • 2019-10-18
                    • 2012-06-30
                    • 2018-06-26
                    • 2015-06-28
                    • 1970-01-01
                    • 2022-10-12
                    相关资源
                    最近更新 更多