使用Python发送电子邮件
阅读原文时间:2021年04月20日阅读:1

You probably found this tutorial because you want to send emails using Python. Perhaps you want to receive email reminders from your code, send a confirmation email to users when they create an account, or send emails to members of your organization to remind them to pay their dues. Sending emails manually is a time-consuming and error-prone task, but it’s easy to automate with Python.

您可能找到了本教程,是因为您想使用Python发送电子邮件。 也许您想从代码中接收电子邮件提醒,在用户创建帐户时向用户发送确认电子邮件,或向组织成员发送电子邮件以提醒他们支付会费。 手动发送电子邮件是一项耗时且容易出错的任务,但是使用Python可以轻松实现自动化。

In this tutorial you’ll learn how to:

在本教程中,您将学习如何

  • Set up a secure connection using SMTP_SSL() and .starttls()

  • Use Python’s built-in smtplib library to send basic emails

  • Send emails with HTML content and attachments using the email package

  • Send multiple personalized emails using a CSV file with contact data

  • Use the Yagmail package to send email through your Gmail account using only a few lines of code

  • 使用SMTP_SSL().starttls()设置安全连接

  • 使用Python的内置smtplib库发送基本电子邮件

  • 使用email包发送带有HTML内容附件email

  • 使用带有联系人数据的CSV文件发送多个个性化电子邮件

  • 使用Yagmail软件包,只需使用几行代码即可通过您的Gmail帐户发送电子邮件

You’ll find a few transactional email services at the end of this tutorial, which will come in useful when you want to send a large number of emails.

在本教程的最后,您会发现一些事务性电子邮件服务,当您要发送大量电子邮件时,这些服务将非常有用。

Free Bonus: Click here to get access to a chapter from Python Tricks: The Book that shows you Python’s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.

免费红利: 单击此处可访问Python技巧的一章:该书通过简单的示例向您展示了Python的最佳实践,您可以立即应用这些示例编写更精美的Pythonic代码。

入门 (Getting Started)

Python comes with the built-in smtplib module for sending emails using the Simple Mail Transfer Protocol (SMTP). smtplib uses the RFC 821 protocol for SMTP. The examples in this tutorial will use the Gmail SMTP server to send emails, but the same principles apply to other email services. Although the majority of email providers use the same connection ports as the ones in this tutorial, you can run a quick Google search to confirm yours.

Python随附有内置的smtplib模块,用于使用简单邮件传输协议(SMTP)发送电子邮件。 smtplib对SMTP使用RFC 821协议。 本教程中的示例将使用Gmail SMTP服务器发送电子邮件,但是相同的原理也适用于其他电子邮件服务。 尽管大多数电子邮件提供商都使用与本教程相同的连接端口,但是您可以运行快速的Google搜索来确认您的连接端口。

To get started with this tutorial, set up a Gmail account for development, or set up an SMTP debugging server that discards emails you send and prints them to the command prompt instead. Both options are laid out for you below. A local SMTP debugging server can be useful for fixing any issues with email functionality and ensuring your email functions are bug-free before sending out any emails.

要开始使用本教程,请设置一个Gmail帐户进行开发 ,或者设置一个SMTP调试服务器 ,该服务器将丢弃您发送的电子邮件,并将其打印到命令提示符下。 下面为您列出了这两种选择。 本地SMTP调试服务器可用于解决电子邮件功能中的任何问题,并确保在发送任何电子邮件之前电子邮件功能无错误。

选项1:设置Gmail开发帐户 (Option 1: Setting up a Gmail Account for Development)

If you decide to use a Gmail account to send your emails, I highly recommend setting up a throwaway account for the development of your code. This is because you’ll have to adjust your Gmail account’s security settings to allow access from your Python code, and because there’s a chance you might accidentally expose your login details. Also, I found that the inbox of my testing account rapidly filled up with test emails, which is reason enough to set up a new Gmail account for development.

如果您决定使用Gmail帐户发送电子邮件,我强烈建议您设置一个用于开发代码的一次性帐户。 这是因为您必须调整Gmail帐户的安全设置,以允许通过Python代码进行访问,并且因为您可能会不小心暴露您的登录详细信息。 另外,我发现测试帐户的收件箱中很快充满了测试电子邮件,这足以为开发设置新的Gmail帐户。

A nice feature of Gmail is that you can use the + sign to add any modifiers to your email address, right before the @ sign. For example, mail sent to my+person1@gmail.com and my+person2@gmail.com will both arrive at my@gmail.com. When testing email functionality, you can use this to emulate multiple addresses that all point to the same inbox.

Gmail的一个不错的功能是,您可以使用+号在@符号前添加任何修饰符到您的电子邮件地址。 例如,发送到my+person1@gmail.commy+person2@gmail.com邮件my+person2@gmail.com将到达my@gmail.com 。 测试电子邮件功能时,您可以使用它来模拟都指向同一收件箱的多个地址。

To set up a Gmail address for testing your code, do the following:

要设置Gmail地址以测试您的代码,请执行以下操作:

If you don’t want to lower the security settings of your Gmail account, check out Google’s documentation on how to gain access credentials for your Python script, using the OAuth2 authorization framework.

如果您不想降低Gmail帐户的安全设置,请查阅Google 文档 ,了解如何使用OAuth2授权框架获取Python脚本的访问凭据。

选项2:设置本地SMTP服务器 (Option 2: Setting up a Local SMTP Server)

You can test email functionality by running a local SMTP debugging server, using the smptd module that comes pre-installed with Python. Rather than sending emails to the specified address, it discards them and prints their content to the console. Running a local debugging server means it’s not necessary to deal with encryption of messages or use credentials to log in to an email server.

您可以使用Python随附的smptd模块,通过运行本地SMTP调试服务器来测试电子邮件功能。 它不会丢弃电子邮件,而是将其内容打印到控制台,而不是将电子邮件发送到指定的地址。 运行本地调试服务器意味着无需处理消息的加密或使用凭据登录电子邮件服务器。

You can start a local SMTP debugging server by typing the following in Command Prompt:

您可以通过在命令提示符中键入以下内容来启动本地SMTP调试服务器:

 $ python -m smtpd -c DebuggingServer -n localhost:1025
$ python -m smtpd -c DebuggingServer -n localhost:1025

On Linux, use the same command preceded by sudo.

在Linux上,使用与sudo相同的命令。

Any emails sent through this server will be discarded and shown in the terminal window as a bytes object for each line:

通过该服务器发送的所有电子邮件都将被丢弃,并在终端窗口中显示为每一行的bytes对象:

For the rest of the tutorial, I’ll assume you’re using a Gmail account, but if you’re using a local debugging server, just make sure to use localhost as your SMTP server and use port 1025 rather than port 465 or 587. Besides this, you won’t need to use login() or encrypt the communication using SSL/TLS.

在本教程的其余部分中,我假设您使用的是Gmail帐户,但是如果您使用的是本地调试服务器,只需确保将localhost用作SMTP服务器,并使用端口1025而不是端口465或587除此之外,您将不需要使用login()或使用SSL / TLS加密通信。

发送纯文本电子邮件 (Sending a Plain-Text Email)

Before we dive into sending emails with HTML content and attachments, you’ll learn to send plain-text emails using Python. These are emails that you could write up in a simple text editor. There’s no fancy stuff like text formatting or hyperlinks. You’ll learn that a bit later.

在我们开始发送带有HTML内容和附件的电子邮件之前,您将学习使用Python发送纯文本电子邮件。 这些是您可以在简单的文本编辑器中编写的电子邮件。 没有花哨的东西,例如文本格式或超链接。 稍后您会学到的。

启动安全的SMTP连接 (Starting a Secure SMTP Connection)

When you send emails through Python, you should make sure that your SMTP connection is encrypted, so that your message and login credentials are not easily accessed by others. SSL (Secure Sockets Layer) and TLS (Transport Layer Security) are two protocols that can be used to encrypt an SMTP connection. It’s not necessary to use either of these when using a local debugging server.

通过Python发送电子邮件时,应确保SMTP连接已加密,以防止他人轻易访问您的消息和登录凭据。 SSL(安全套接字层)和TLS(传输层安全性)是两个可用于加密SMTP连接的协议。 使用本地调试服务器时,不必使用这两种方法。

There are two ways to start a secure connection with your email server:

有两种方法可以启动与电子邮件服务器的安全连接:

  • Start an SMTP connection that is secured from the beginning using SMTP_SSL().

  • Start an unsecured SMTP connection that can then be encrypted using .starttls().

  • 使用SMTP_SSL()开始保护SMTP连接。

  • 启动不安全的SMTP连接,然后可以使用.starttls()对其进行加密。

In both instances, Gmail will encrypt emails using TLS, as this is the more secure successor of SSL. As per Python’s Security considerations, it is highly recommended that you use create_default_context() from the ssl module. This will load the system’s trusted CA certificates, enable host name checking and certificate validation, and try to choose reasonably secure protocol and cipher settings.

在这两种情况下,Gmail都会使用TLS加密电子邮件,因为这是SSL的更安全的继承者。 根据Python的安全性考虑 ,强烈建议您使用ssl模块中的create_default_context() 。 这将加载系统的受信任CA证书,启用主机名检查和证书验证,并尝试选择合理的安全协议和密码设置。

If you want to check the encryption for an email in your Gmail inbox, go to More → Show original to see the encryption type listed under the Received header.

如果要在Gmail收件箱中检查电子邮件的加密,请转到“更多”→“显示原始邮件”以查看“已接收”标题下列出的加密类型。

smtplib is Python’s built-in module for sending emails to any Internet machine with an SMTP or ESMTP listener daemon.

smtplib是Python的内置模块,用于通过SMTP或ESMTP侦听器守护程序将电子邮件发送到任何Internet机器。

I’ll show you how to use SMTP_SSL() first, as it instantiates a connection that is secure from the outset and is slightly more concise than the .starttls() alternative. Keep in mind that Gmail requires that you connect to port 465 if using SMTP_SSL(), and to port 587 when using .starttls().

我将首先向您展示如何使用SMTP_SSL() ,因为它实例化了从一开始就安全的连接,并且比.starttls()更为简洁。 请记住,Gmail要求您如果使用连接到端口465 SMTP_SSL()和端口587,使用时.starttls()

选项1:使用SMTP_SSL() (Option 1: Using SMTP_SSL())

The code example below creates a secure connection with Gmail’s SMTP server, using the SMTP_SSL() of smtplib to initiate a TLS-encrypted connection. The default context of ssl validates the host name and its certificates and optimizes the security of the connection. Make sure to fill in your own email address instead of my@gmail.com:

下面的代码示例使用smtplibSMTP_SSL()启动TLS加密的连接,从而与Gmail的SMTP服务器建立安全连接。 ssl的默认上下文验证主机名及其证书,并优化连接的安全性。 确保填写您自己的电子邮件地址,而不是my@gmail.com

 import import smtplibsmtplib , , ssl

ssl

port port = = 465  465  # For SSL
# For SSL
password password = = inputinput (( "Type your password and press enter: ""Type your password and press enter: " )

)

# Create a secure SSL context
# Create a secure SSL context
context context = = sslssl .. create_default_contextcreate_default_context ()

()

with with smtplibsmtplib .. SMTP_SSLSMTP_SSL (( "smtp.gmail.com""smtp.gmail.com" , , portport , , contextcontext == contextcontext ) ) as as serverserver :
    :
    serverserver .. loginlogin (( "my@gmail.com""my@gmail.com" , , passwordpassword )
    )
    # TODO: Send email here
# TODO: Send email here

Using with smtplib.SMTP_SSL() as server: makes sure that the connection is automatically closed at the end of the indented code block. If port is zero, or not specified, .SMTP_SSL() will use the standard port for SMTP over SSL (port 465).

with smtplib.SMTP_SSL() as server:确保在缩进代码块的末尾自动关闭连接。 如果port为零或未指定, .SMTP_SSL()将使用基于SSL的SMTP的标准端口(端口465)。

It’s not safe practice to store your email password in your code, especially if you intend to share it with others. Instead, use input() to let the user type in their password when running the script, as in the example above. If you don’t want your password to show on your screen when you type it, you can import the getpass module and use .getpass() instead for blind input of your password.

将您的电子邮件密码存储在代码中是不安全的做法,特别是如果您打算与他人共享。 而是使用input()来让用户在运行脚本时输入其密码,如上例所示。 如果您不希望在键入密码时在屏幕上显示密码,则可以导入getpass模块并使用.getpass()代替盲目输入密码。

选项2:使用.starttls() (Option 2: Using .starttls())

Instead of using .SMTP_SSL() to create a connection that is secure from the outset, we can create an unsecured SMTP connection and encrypt it using .starttls().

无需使用.SMTP_SSL()创建从一开始就安全的连接,我们可以创建不安全的SMTP连接并使用.starttls()对其进行加密。

To do this, create an instance of smtplib.SMTP, which encapsulates an SMTP connection and allows you access to its methods. I recommend defining your SMTP server and port at the beginning of your script to configure them easily.

为此,请创建一个smtplib.SMTP实例,该实例封装了一个SMTP连接,并允许您访问其方法。 我建议在脚本的开头定义SMTP服务器和端口,以轻松配置它们。

The code snippet below uses the construction server = SMTP(), rather than the format with SMTP() as server: which we used in the previous example. To make sure that your code doesn’t crash when something goes wrong, put your main code in a try block, and let an except block print any error messages to stdout:

下面的代码片段使用构造server = SMTP() ,而不是with SMTP() as server:的格式with SMTP() as server:我们在前面的示例中使用了该格式。 为了确保您的代码在出现问题时不会崩溃,请将您的主代码放在try块中,并让except块将所有错误消息打印到stdout

To identify yourself to the server, .helo() (SMTP) or .ehlo() (ESMTP) should be called after creating an .SMTP() object, and again after .starttls(). This function is implicitly called by .starttls() and .sendmail() if needed, so unless you want to check the SMTP service extensions of the server, it is not necessary to use .helo() or .ehlo() explicitly.

为了向服务器标识自己,应该在创建.SMTP()对象之后,然后在.starttls()之后再次调用.helo() (SMTP)或.ehlo() (ESMTP .starttls() 。 如果需要,此函数将由.starttls().sendmail()隐式调用,因此,除非您要检查服务器的SMTP服务扩展名,否则不必显式使用.helo().ehlo()

发送纯文本电子邮件 (Sending Your Plain-text Email)

After you initiated a secure SMTP connection using either of the above methods, you can send your email using .sendmail(), which pretty much does what it says on the tin:

使用上述任何一种方法启动安全的SMTP连接之后,您都可以使用.sendmail()发送电子邮件,该电子邮件几乎可以执行以下操作:

 serverserver .. sendmailsendmail (( sender_emailsender_email , , receiver_emailreceiver_email , , messagemessage )
)

I recommend defining the email addresses and message content at the top of your script, after the imports, so you can change them easily:

我建议在导入之后在脚本顶部定义电子邮件地址和消息内容,以便您可以轻松更改它们:

The message string starts with "Subject: Hi there" followed by two newlines (n). This ensures Hi there shows up as the subject of the email, and the text following the newlines will be treated as the message body.

message 字符串"Subject: Hi there"开头,后跟两个换行符( n )。 这样可以确保Hi there显示为电子邮件的主题,而换行符之后的文本将被视为消息正文。

The code example below sends a plain-text email using SMTP_SSL():

下面的代码示例使用SMTP_SSL()发送纯文本电子邮件:

 import import smtplibsmtplib , , ssl

ssl

port port = = 465  465  # For SSL
# For SSL
smtp_server smtp_server = = "smtp.gmail.com"
"smtp.gmail.com"
sender_email sender_email = = "my@gmail.com"  "my@gmail.com"  # Enter your address
# Enter your address
receiver_email receiver_email = = "your@gmail.com"  "your@gmail.com"  # Enter receiver address
# Enter receiver address
password password = = inputinput (( "Type your password and press enter: ""Type your password and press enter: " )
)
message message = = """""" 

Subject: Hi there

Subject: Hi there

This message is sent from Python."""

This message is sent from Python."""

context context = = sslssl .. create_default_contextcreate_default_context ()
()
with with smtplibsmtplib .. SMTP_SSLSMTP_SSL (( smtp_serversmtp_server , , portport , , contextcontext == contextcontext ) ) as as serverserver :
    :
    serverserver .. loginlogin (( sender_emailsender_email , , passwordpassword )
    )
    serverserver .. sendmailsendmail (( sender_emailsender_email , , receiver_emailreceiver_email , , messagemessage )
)

For comparison, here is a code example that sends a plain-text email over an SMTP connection secured with .starttls(). The server.ehlo() lines may be omitted, as they are called implicitly by .starttls() and .sendmail(), if required:

为了进行比较,下面是一个代码示例,该示例通过受.starttls()保护的SMTP连接发送纯文本电子邮件。 server.ehlo()行可以省略,因为如果需要,它们可以由.starttls().sendmail()隐式调用:

发送精美的电子邮件 (Sending Fancy Emails)

Python’s built-in email package allows you to structure more fancy emails, which can then be transferred with smptlib as you have done already. Below, you’ll learn how use the email package to send emails with HTML content and attachments.

Python的内置email程序包使您可以构建更多精美的电子邮件,然后就可以通过smptlib进行传输了。 下面,您将学习如何使用email包发送带有HTML内容和附件的电子邮件。

包括HTML内容 (Including HTML Content)

If you want to format the text in your email (bold, italics, and so on), or if you want to add any images, hyperlinks, or responsive content, then HTML comes in very handy. Today’s most common type of email is the MIME (Multipurpose Internet Mail Extensions) Multipart email, combining HTML and plain-text. MIME messages are handled by Python’s email.mime module. For a detailed description, check the documentation.

如果要格式化电子邮件中的文本格式( 粗体 ,斜体等),或者要添加任何图像,超链接或响应内容,则HTML非常方便。 当今最常见的电子邮件类型是MIME(多用途Internet邮件扩展)多部分电子邮件,它结合了HTML和纯文本。 MIME消息由Python的email.mime模块处理。 有关详细说明,请参阅文档

As not all email clients display HTML content by default, and some people choose only to receive plain-text emails for security reasons, it is important to include a plain-text alternative for HTML messages. As the email client will render the last multipart attachment first, make sure to add the HTML message after the plain-text version.

由于并非所有电子邮件客户端默认情况下都显示HTML内容,并且某些人出于安全原因仅选择接收纯文本电子邮件,因此为HTML消息包括纯文本替代品很重要。 由于电子邮件客户端将首先呈现最后的多部分附件,因此请确保在纯文本版本之后添加HTML消息。

In the example below, our MIMEText() objects will contain the HTML and plain-text versions of our message, and the MIMEMultipart("alternative") instance combines these into a single message with two alternative rendering options:

在下面的示例中,我们的MIMEText()对象将包含消息HTML版本和纯文本版本,而MIMEMultipart("alternative")实例将这些消息合并为具有两个替代呈现选项的单个消息:

 import import smtplibsmtplib , , ssl
ssl
from from email.mime.text email.mime.text import import MIMEText
MIMEText
from from email.mime.multipart email.mime.multipart import import MIMEMultipart

MIMEMultipart

sender_email sender_email = = "my@gmail.com"
"my@gmail.com"
receiver_email receiver_email = = "your@gmail.com"
"your@gmail.com"
password password = = inputinput (( "Type your password and press enter:""Type your password and press enter:" )

)

message message = = MIMEMultipartMIMEMultipart (( "alternative""alternative" )
)
messagemessage [[ "Subject""Subject" ] ] = = "multipart test"
"multipart test"
messagemessage [[ "From""From" ] ] = = sender_email
sender_email
messagemessage [[ "To""To" ] ] = = receiver_email

receiver_email

# Create the plain-text and HTML version of your message
# Create the plain-text and HTML version of your message
text text = = """""" 

Hi,
Hi,
How are you?
How are you?
Real Python has many great tutorials:
Real Python has many great tutorials:
www.realpython.com"""
www.realpython.com"""
html html = = """""" 

<html>
<html>
  <body>
  <body>
    <p>Hi,<br>
    <p>Hi,<br>
       How are you?<br>
       How are you?<br>
       <a href="http://www.realpython.com">Real Python</a> 
       <a href="http://www.realpython.com">Real Python</a> 
       has many great tutorials.
       has many great tutorials.
    </p>
    </p>
  </body>
  </body>
</html>
</html>
"""

"""

# Turn these into plain/html MIMEText objects
# Turn these into plain/html MIMEText objects
part1 part1 = = MIMETextMIMEText (( texttext , , "plain""plain" )
)
part2 part2 = = MIMETextMIMEText (( htmlhtml , , "html""html" )

)

# Add HTML/plain-text parts to MIMEMultipart message
# Add HTML/plain-text parts to MIMEMultipart message
# The email client will try to render the last part first
# The email client will try to render the last part first
messagemessage .. attachattach (( part1part1 )
)
messagemessage .. attachattach (( part2part2 )

)

# Create secure connection with server and send email
# Create secure connection with server and send email
context context = = sslssl .. create_default_contextcreate_default_context ()
()
with with smtplibsmtplib .. SMTP_SSLSMTP_SSL (( "smtp.gmail.com""smtp.gmail.com" , , 465465 , , contextcontext == contextcontext ) ) as as serverserver :
    :
    serverserver .. loginlogin (( sender_emailsender_email , , passwordpassword )
    )
    serverserver .. sendmailsendmail (
        (
        sender_emailsender_email , , receiver_emailreceiver_email , , messagemessage .. as_stringas_string ()
    ()
    )
)

In this example, you first define the plain-text and HTML message as string literals, and then store them as plain/html MIMEText objects. These can then be added in this order to the MIMEMultipart("alternative") message and sent through your secure connection with the email server. Remember to add the HTML message after the plain-text alternative, as email clients will try to render the last subpart first.

在此示例中,您首先将纯文本和HTML消息定义为字符串文字,然后将它们存储为plain / html MIMEText对象。 然后可以按此顺序将它们添加到MIMEMultipart("alternative")消息中,并通过与电子邮件服务器的安全连接进行发送。 请记住在纯文本替代项之后添加HTML消息,因为电子邮件客户端将尝试首先呈现最后一个子部分。

使用email包添加附件 (Adding Attachments Using the email Package)

In order to send binary files to an email server that is designed to work with textual data, they need to be encoded before transport. This is most commonly done using base64, which encodes binary data into printable ASCII characters.

为了将二进制文件发送到旨在处理文本数据的电子邮件服务器,需要在传输之前对它们进行编码。 这通常是使用base64完成的,后者将二进制数据编码为可打印的ASCII字符。

The code example below shows how to send an email with a PDF file as an attachment:

下面的代码示例显示了如何发送带有PDF文件作为附件的电子邮件:

The MIMEultipart() message accepts parameters in the form of RFC5233-style key/value pairs, which are stored in a dictionary and passed to the .add_header method of the Message base class.

MIMEultipart()消息接受RFC5233样式键/值对形式的参数,这些参数存储在字典中并传递给Message基类的.add_header方法

Check out the documentation for Python’s email.mime module to learn more about using MIME classes.

查看Python的email.mime模块的文档 ,以了解有关使用MIME类的更多信息。

发送多个个性化电子邮件 (Sending Multiple Personalized Emails)

Imagine you want to send emails to members of your organization, to remind them to pay their contribution fees. Or maybe you want to send students in your class personalized emails with the grades for their recent assignment. These tasks are a breeze in Python.

想象一下,您想向组织成员发送电子邮件,以提醒他们支付其会费。 或者,您可能想在班级中向学生发送个性化的电子邮件,其中包含他们最近的作业成绩。 这些任务在Python中轻而易举。

制作包含相关个人信息的CSV文件 (Make a CSV File With Relevant Personal Info)

An easy starting point for sending multiple personalized emails is to create a CSV (comma-separated values) file that contains all the required personal information. (Make sure not to share other people’s private information without their consent.) A CSV file can be thought of as a simple table, where the first line often contains the column headers.

发送多个个性化电子邮件的简单起点是创建一个包含所有必需的个人信息的CSV(逗号分隔值)文件 。 (请确保不要在未经他人同意的情况下共享其他人的私人信息。)CSV文件可以看作是一个简单的表,其中第一行通常包含列标题。

Below are the contents of the file contacts_file.csv, which I saved in the same folder as my Python code. It contains the names, addresses, and grades for a set of fictional people. I used my+modifier@gmail.com constructions to make sure all emails end up in my own inbox, which in this example is my@gmail.com:

以下是文件contacts_file.csv的内容,该文件contacts_file.csv Python代码保存在同一文件夹中。 它包含一组虚构人员的姓名,地址和等级。 我使用my+modifier@gmail.com构造来确保所有电子邮件最终都放在我自己的收件箱中,在此示例中为my@gmail.com :

name,email,grade
Ron Obvious,my+ovious@gmail.com,B+
Killer Rabbit of Caerbannog,my+rabbit@gmail.com,A
Brian Cohen,my+brian@gmail.com,C
name,email,grade
Ron Obvious,my+ovious@gmail.com,B+
Killer Rabbit of Caerbannog,my+rabbit@gmail.com,A
Brian Cohen,my+brian@gmail.com,C

When creating a CSV file, make sure to separate your values by a comma, without any surrounding whitespaces.

创建CSV文件时,请确保用逗号分隔值,且周围没有空格。

循环行发送多封电子邮件 (Loop Over Rows to Send Multiple Emails)

The code example below shows you how to open a CSV file and loop over its lines of content (skipping the header row). To make sure that the code works correctly before you send emails to all your contacts, I’ve printed Sending email to ... for each contact, which we can later replace with functionality that actually sends out emails:

下面的代码示例向您展示如何打开CSV文件并在其内容行之间循环(跳过标题行)。 为确保代码在向所有联系人发送电子邮件之前能正常工作,我已为每个联系人打印了“ Sending email to ... ,我们稍后可以将其替换为实际发送电子邮件的功能:

In the example above, using with open(filename) as file:makes sure that your file closes at the end of the code block. csv.reader() makes it easy to read a CSV file line by line and extract its values. The next(reader) line skips the header row, so that the following line for name, email, grade in reader: splits subsequent rows at each comma, and stores the resulting values in the strings name, email and grade for the current contact.

在上面的示例中,使用with open(filename) as file:确保您的文件在代码块的末尾关闭。 csv.reader()可以轻松地逐行读取CSV文件并提取其值。 next(reader)跳过标题行,以便for name, email, grade in reader:中的nameemailgrade下面一行for name, email, grade in reader:在每个逗号处拆分后续行,并将结果值存储在字符串中,当前联系人的nameemailgrade

If the values in your CSV file contain whitespaces on either or both sides, you can remove them using the .strip() method.

如果CSV文件中的值在两侧或两侧包含空格,则可以使用.strip()方法将其删除。

个性化内容 (Personalized Content)

You can put personalized content in a message by using str.format() to fill in curly-bracket placeholders. For example, "hi {name}, you {result} your assignment".format(name="John", result="passed") will give you "hi John, you passed your assignment".

您可以使用str.format()填写大括号的占位符,从而在邮件中放入个性化内容。 例如, "hi {name}, you {result} your assignment".format(name="John", result="passed")将给您"hi John, you passed your assignment"

As of Python 3.6, string formatting can be done more elegantly using f-strings, but these require the placeholders to be defined before the f-string itself. In order to define the email message at the beginning of the script, and fill in placeholders for each contact when looping over the CSV file, the older .format() method is used.

从Python 3.6开始,可以使用f-strings更好地完成字符串格式化,但是这些要求在f-string本身之前定义占位符。 为了在脚本的开头定义电子邮件,并在循环CSV文件时为每个联系人填写占位符,使用了较旧的.format()方法。

With this in mind, you can set up a general message body, with placeholders that can be tailored to individuals.

考虑到这一点,您可以设置一个通用的邮件正文,其中的占位符可以针对个人量身定制。

代码示例 (Code Example)

The following code example lets you send personalized emails to multiple contacts. It loops over a CSV file with name,email,grade for each contact, as in the example above.

以下代码示例使您可以向多个联系人发送个性化电子邮件。 如上面示例所示 ,它循环遍历每个联系人的name,email,grade的CSV文件。

The general message is defined in the beginning of the script, and for each contact in the CSV file its {name} and {grade} placeholders are filled in, and a personalized email is sent out through a secure connection with the Gmail server, as you saw before:

常规消息在脚本的开头定义,并为CSV文件中的每个联系人填充其{name}{grade}占位符,并通过与Gmail服务器的安全连接发送个性化电子邮件,如下所示:您之前看过:

 import import csvcsv , , smtplibsmtplib , , ssl

ssl

message message = = """Subject: Your grade

"""Subject: Your grade

Hi Hi  {name}{name} , your grade is , your grade is  {grade}{grade} """
"""
from_address from_address = = "my@gmail.com"
"my@gmail.com"
password password = = inputinput (( "Type your password and press enter: ""Type your password and press enter: " )

)

context context = = sslssl .. create_default_contextcreate_default_context ()
()
with with smtplibsmtplib .. SMTP_SSLSMTP_SSL (( "smtp.gmail.com""smtp.gmail.com" , , 465465 , , contextcontext == contextcontext ) ) as as serverserver :
    :
    serverserver .. loginlogin (( from_addressfrom_address , , passwordpassword )
    )
    with with openopen (( "contacts_file.csv""contacts_file.csv" ) ) as as filefile :
        :
        reader reader = = csvcsv .. readerreader (( filefile )
        )
        nextnext (( readerreader )  )  # Skip header row
        # Skip header row
        for for namename , , emailemail , , grade grade in in readerreader :
            :
            serverserver .. sendmailsendmail (
                (
                from_addressfrom_address ,
                ,
                emailemail ,
                ,
                messagemessage .. formatformat (( namename == namename ,, gradegrade == gradegrade ),
            ),
            )
)

Yagmail (Yagmail)

There are multiple libraries designed to make sending emails easier, such as Envelopes, Flanker and Yagmail. Yagmail is designed to work specifically with Gmail, and it greatly simplifies the process of sending emails through a friendly API, as you can see in the code example below:

有多个库旨在简化发送电子邮件的过程,例如EnvelopesFlankerYagmail 。 Yagmail专门设计用于Gmail,它极大地简化了通过友好的API发送电子邮件的过程,如下面的代码示例所示:

This code example sends an email with a PDF attachment in a fraction of the lines needed for our example using email and smtplib.

此代码示例使用emailsmtplib在本示例所需的几行中发送带有PDF附件的email

When setting up Yagmail, you can add your Gmail validations to the keyring of your OS, as described in the documentation. If you don’t do this, Yagmail will prompt you to enter your password when required and store it in the keyring automatically.

设置Yagmail时,您可以按照文档的说明将Gmail验证添加到操作系统的密钥环。 如果您不这样做,Yagmail将在需要时提示您输入密码,并将其自动存储在钥匙圈中。

交易电子邮件服务 (Transactional Email Services)

If you plan to send a large volume of emails, want to see email statistics, and want to ensure reliable delivery, it may be worth looking into transactional email services. Although all of the following services have paid plans for sending large volumes of emails, they also come with a free plan so you can try them out. Some of these free plans are valid indefinitely and may be sufficient for your email needs.

如果您打算发送大量电子邮件,希望查看电子邮件统计信息并希望确保可靠的传递,那么值得考虑使用事务性电子邮件服务。 尽管以下所有服务均已支付了发送大量电子邮件的计划,但它们还提供免费计划,因此您可以尝试一下。 其中一些免费计划无限期有效,可能足以满足您的电子邮件需求。

Below is an overview of the free plans for some of the major transactional email services. Clicking on the provider name will take you to the pricing section of their website.

以下是一些主要交易电子邮件服务的免费计划的概述。 单击提供商名称将带您进入其网站的定价部分。

Provider

提供者

Free plan

免费计划

Sendgrid森格

40,000 emails for your first 30 days, then 100/day

前30天40,000封电子邮件,然后每天100封电子邮件

Sendinblue森丁蓝

300 emails/day

每天300封电子邮件

MailgunMailgun

First 10,000 emails free

前10,000个电子邮件免费

MailjetMailjet

200 emails/day

每天200封电子邮件

Amazon SES亚马逊SES

62,000 emails/month

每月62,000封电子邮件

You can run a Google search to see which provider best fits your needs, or just try out a few of the free plans to see which API you like working with most.

您可以运行Google搜索来查看最适合您需求的提供商,也可以尝试一些免费计划以查看最喜欢使用哪个API。

Sendgrid代码示例 (Sendgrid Code Example)

Here’s a code example for sending emails with Sendgrid to give you a flavor of how to use a transactional email service with Python:

这是一个使用Sendgrid发送电子邮件的代码示例,使您了解如何在Python中使用事务性电子邮件服务:

 import import os
os
import import sendgrid
sendgrid
from from sendgrid.helpers.mail sendgrid.helpers.mail import import ContentContent , , EmailEmail , , Mail

Mail

sg sg = = sendgridsendgrid .. SendGridAPIClientSendGridAPIClient (
    (
    apikeyapikey == osos .. environenviron .. getget (( "SENDGRID_API_KEY""SENDGRID_API_KEY" )
)
)
)
from_email from_email = = EmailEmail (( "my@gmail.com""my@gmail.com" )
)
to_email to_email = = EmailEmail (( "your@gmail.com""your@gmail.com" )
)
subject subject = = "A test email from Sendgrid"
"A test email from Sendgrid"
content content = = ContentContent (
    (
    "text/plain""text/plain" , , "Here's a test email sent through Python"
"Here's a test email sent through Python"
)
)
mail mail = = MailMail (( from_emailfrom_email , , subjectsubject , , to_emailto_email , , contentcontent )
)
response response = = sgsg .. clientclient .. mailmail .. sendsend .. postpost (( request_bodyrequest_body == mailmail .. getget ())

())

# The statements below can be included for debugging purposes
# The statements below can be included for debugging purposes
printprint (( responseresponse .. status_codestatus_code )
)
printprint (( responseresponse .. bodybody )
)
printprint (( responseresponse .. headersheaders )
)

To run this code, you must first:

要运行此代码,您必须首先:

  • Sign up for a (free) Sendgrid account

  • Request an API key for user validation

  • Add your API key by typing setx SENDGRID_API_KEY "YOUR_API_KEY" in Command Prompt (to store this API key permanently) or set SENDGRID_API_KEY YOUR_API_KEY to store it only for the current client session

  • 注册一个(免费)Sendgrid帐户

  • 请求API密钥以进行用户验证

  • 通过在命令提示符下键入setx SENDGRID_API_KEY "YOUR_API_KEY"添加API密钥(以永久存储此API密钥),或set SENDGRID_API_KEY YOUR_API_KEY为仅将其存储在当前客户端会话中

More information on how to set up Sendgrid for Mac and Windows can be found in the repository’s README on Github.

有关如何在Mac和Windows上设置Sendgrid的更多信息,可以在Github上的存储库README中找到。

结论 (Conclusion)

You can now start a secure SMTP connection and send multiple personalized emails to the people in your contacts list!

现在,您可以启动安全的SMTP连接,并向联系人列表中的人发送多封个性化电子邮件!

You’ve learned how to send an HTML email with a plain-text alternative and attach files to your emails. The Yagmail package simplifies all these tasks when you’re using a Gmail account. If you plan to send large volumes of email, it is worth looking into transactional email services.

您已经了解了如何发送带有纯文本替代格式HTML电子邮件以及如何将文件附加到电子邮件中。 使用Gmail帐户时, Yagmail软件包可简化所有这些任务。 如果您打算发送大量电子邮件,则值得研究交易电子邮件服务。

Enjoy sending emails with Python, and remember: no spam please!

喜欢用Python发送电子邮件,并记住: 请不要发送垃圾邮件

翻译自: https://www.pybloggers.com/2018/12/sending-emails-with-python/

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器