如何使用 Python 发送以 Gmail 为提供商的电子邮件?
- 2024-12-12 08:40:00
- admin 原创
- 151
问题描述:
我正在尝试使用 python 发送电子邮件(Gmail),但出现以下错误。
Traceback (most recent call last):
File "emailSend.py", line 14, in <module>
server.login(username,password)
File "/usr/lib/python2.5/smtplib.py", line 554, in login
raise SMTPException("SMTP AUTH extension not supported by server.")
smtplib.SMTPException: SMTP AUTH extension not supported by server.
Python 脚本如下。
import smtplib
fromaddr = 'user_me@gmail.com'
toaddrs = 'user_you@gmail.com'
msg = 'Why,Oh why!'
username = 'user_me@gmail.com'
password = 'pwd'
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
解决方案 1:
def send_email(user, pwd, recipient, subject, body):
import smtplib
FROM = user
TO = recipient if isinstance(recipient, list) else [recipient]
SUBJECT = subject
TEXT = body
# Prepare actual message
message = """From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
try:
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(user, pwd)
server.sendmail(FROM, TO, message)
server.close()
print 'successfully sent the mail'
except:
print "failed to send mail"
如果您想使用端口 465,您必须创建一个SMTP_SSL
对象:
# SMTP_SSL Example
server_ssl = smtplib.SMTP_SSL("smtp.gmail.com", 465)
server_ssl.ehlo() # optional, called by login()
server_ssl.login(gmail_user, gmail_pwd)
# ssl server doesn't support or need tls, so don't call server_ssl.starttls()
server_ssl.sendmail(FROM, TO, message)
#server_ssl.quit()
server_ssl.close()
print 'successfully sent the mail'
解决方案 2:
EHLO
在直接运行之前你需要说STARTTLS
:
server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo()
server.starttls()
您还应该真正创建From:
和消息头To:
,Subject:
用空行与消息正文分开,并用作CRLF
EOL 标记。
例如
msg = "
".join([
"From: user_me@gmail.com",
"To: user_you@gmail.com",
"Subject: Just a message",
"",
"Why, oh why"
])
笔记:
为了实现此功能,您需要在 Gmail 帐户配置中启用“允许安全性较低的应用程序”选项。否则,当 Gmail 检测到非 Google 应用程序试图登录您的帐户时,您将收到“严重安全警报”。
解决方案 3:
截至 2024 年,有效方式如下:
转到https://myaccount.google.com/security并确保您的帐户已启用两步验证。为此,您可以在手机上设置一个应用程序,例如 Google Authenticator、authy 等。
设置“两步验证”后,从安全性再次转到“两步验证”,然后向下滚动到“应用程序密码”:
现在为您的应用程序命名,您将获得设备的密码。
最后将您的密码保存在安全的地方,并将您的电子邮件和密码输入以下脚本:
import smtplib
YOUR_GOOGLE_EMAIL = '<you@gmail.com>' # The email you setup to send the email using app password
YOUR_GOOGLE_EMAIL_APP_PASSWORD = '<your-app-password>' # The app password you generated
smtpserver = smtplib.SMTP_SSL('smtp.gmail.com', 465)
smtpserver.ehlo()
smtpserver.login(YOUR_GOOGLE_EMAIL, YOUR_GOOGLE_EMAIL_APP_PASSWORD)
# Test send mail
sent_from = YOUR_GOOGLE_EMAIL
sent_to = sent_from # Send it to self (as test)
email_text = 'This is a test'
smtpserver.sendmail(sent_from, sent_to, email_text)
# Close the connection
smtpserver.close()
有关更多详细信息,请参阅Google Auth 密码。
旧答案:(这不再有效)我遇到了类似的问题,并偶然发现了这个问题。我收到 SMTP 身份验证错误,但我的用户名/密码是正确的。以下是修复方法。我读到过:
https://support.google.com/accounts/answer/6010255
简而言之,谷歌不允许您通过 smtplib 登录,因为它将这种登录标记为“不太安全”,因此您需要做的是在登录到您的谷歌帐户时转到此链接,并允许访问:
https://www.google.com/settings/security/lesssecureapps
一旦设置完毕(见下面的屏幕截图),它就可以工作了。
登录现在有效:
smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo()
smtpserver.login('me@gmail.com', 'me_pass')
更改后响应:
(235, '2.7.0 Accepted')
先前的回应:
smtplib.SMTPAuthenticationError: (535, '5.7.8 Username and Password not accepted. Learn more at
5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257 g66sm2224117qgf.37 - gsmtp')
仍然无法正常工作?如果您仍然收到 SMTPAuthenticationError 但现在代码为 534,这是因为位置未知。请访问以下链接:
https://accounts.google.com/DisplayUnlockCaptcha
点击继续,您将有 10 分钟的时间来注册新应用。现在继续进行另一次登录尝试,应该可以成功。
更新:这似乎不能立即起作用,您可能会卡住一段时间,在 smptlib 中收到此错误:
235 == 'Authentication successful'
503 == 'Error: already authenticated'
该消息提示使用浏览器登录:
SMTPAuthenticationError: (534, '5.7.9 Please log in with your web browser and then try again. Learn more at
5.7.9 https://support.google.com/mail/bin/answer.py?answer=78754 qo11sm4014232igb.17 - gsmtp')
启用“lesssecureapps”后,去喝杯咖啡,回来后再次尝试“DisplayUnlockCaptcha”链接。根据用户体验,更改可能需要长达一小时才能生效。然后再次尝试登录过程。
您现在还需要按照此处“创建和使用应用密码”部分下的步骤创建应用密码:support.google.com/accounts/answer/185833
解决方案 4:
这有效
创建Gmail APP密码!
创建完成后,创建一个名为sendgmail.py
然后添加以下代码:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# =============================================================================
# Created By : Jeromie Kirchoff
# Created Date: Mon Aug 02 17:46:00 PDT 2018
# =============================================================================
# Imports
# =============================================================================
import smtplib
# =============================================================================
# SET EMAIL LOGIN REQUIREMENTS
# =============================================================================
gmail_user = 'THEFROM@gmail.com'
gmail_app_password = 'YOUR-GOOGLE-APPLICATION-PASSWORD!!!!'
# =============================================================================
# SET THE INFO ABOUT THE SAID EMAIL
# =============================================================================
sent_from = gmail_user
sent_to = ['THE-TO@gmail.com', 'THE-TO@gmail.com']
sent_subject = "Hey Friends!"
sent_body = ("Hey, what's up? friend!
"
"I hope you have been well!
"
"
"
"Cheers,
"
"Jay
")
email_text = """\nFrom: %s
To: %s
Subject: %s
%s
""" % (sent_from, ", ".join(sent_to), sent_subject, sent_body)
# =============================================================================
# SEND EMAIL OR DIE TRYING!!!
# Details: http://www.samlogic.net/articles/smtp-commands-reference.htm
# =============================================================================
try:
server = smtplib.SMTP_SSL('smtp.gmail.com', 465)
server.ehlo()
server.login(gmail_user, gmail_app_password)
server.sendmail(sent_from, sent_to, email_text)
server.close()
print('Email sent!')
except Exception as exception:
print("Error: %s!
" % exception)
所以,如果你成功了,将会看到这样的图像:
我通过向自己发送电子邮件进行了测试。
注意:我的帐户已启用两步验证。App Password 可与此配合使用!(对于 gmail smtp 设置,您必须转到https://support.google.com/accounts/answer/185833?hl=en并按照以下步骤操作)
此设置不适用于已启用两步验证的帐户。此类帐户需要应用程序专用密码才能访问安全性较低的应用程序。
澄清
导航至https://myaccount.google.com/apppasswords并按照上述步骤创建 APP 密码。
解决方案 5:
以下是 Gmail API 示例。虽然更复杂,但这是我发现的唯一在 2019 年有效的方法。此示例取自并修改自:
https://developers.google.com/gmail/api/guides/sending
您需要通过 Google 的网站创建一个包含 Google API 接口的项目。接下来,您需要为您的应用启用 GMAIL API。创建凭据,然后下载这些凭据,将其保存为 credentials.json。
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from email.mime.text import MIMEText
import base64
#pip install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/gmail.readonly', 'https://www.googleapis.com/auth/gmail.send']
def create_message(sender, to, subject, msg):
message = MIMEText(msg)
message['to'] = to
message['from'] = sender
message['subject'] = subject
# Base 64 encode
b64_bytes = base64.urlsafe_b64encode(message.as_bytes())
b64_string = b64_bytes.decode()
return {'raw': b64_string}
#return {'raw': base64.urlsafe_b64encode(message.as_string())}
def send_message(service, user_id, message):
#try:
message = (service.users().messages().send(userId=user_id, body=message).execute())
print( 'Message Id: %s' % message['id'] )
return message
#except errors.HttpError, error:print( 'An error occurred: %s' % error )
def main():
"""Shows basic usage of the Gmail API.
Lists the user's Gmail labels.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('gmail', 'v1', credentials=creds)
# Example read operation
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
if not labels:
print('No labels found.')
else:
print('Labels:')
for label in labels:
print(label['name'])
# Example write
msg = create_message("from@gmail.com", "to@gmail.com", "Subject", "Msg")
send_message( service, 'me', msg)
if __name__ == '__main__':
main()
解决方案 6:
你对 OOP 不满意吗?
#!/usr/bin/env python
import smtplib
class Gmail(object):
def __init__(self, email, password):
self.email = email
self.password = password
self.server = 'smtp.gmail.com'
self.port = 587
session = smtplib.SMTP(self.server, self.port)
session.ehlo()
session.starttls()
session.ehlo
session.login(self.email, self.password)
self.session = session
def send_message(self, subject, body):
''' This must be removed '''
headers = [
"From: " + self.email,
"Subject: " + subject,
"To: " + self.email,
"MIME-Version: 1.0",
"Content-Type: text/html"]
headers = "
".join(headers)
self.session.sendmail(
self.email,
self.email,
headers + "
" + body)
gm = Gmail('Your Email', 'Password')
gm.send_message('Subject', 'Message')
解决方案 7:
虽然没有直接关系,但仍然值得指出的是,我的包试图让发送 Gmail 消息变得非常快速和轻松。它还试图维护错误列表并试图立即指出解决方案。
它实际上只需要这段代码就可以完成你所写的操作:
import yagmail
yag = yagmail.SMTP('user_me@gmail.com')
yag.send('user_you@gmail.com', 'Why,Oh why!')
或者一行:
yagmail.SMTP('user_me@gmail.com').send('user_you@gmail.com', 'Why,Oh why!')
对于包/安装,请查看git或pip,适用于 Python 2 和 3。
解决方案 8:
您可以在这里找到它: http: //jayrambhia.com/blog/send-emails-using-python
smtp_host = 'smtp.gmail.com'
smtp_port = 587
server = smtplib.SMTP()
server.connect(smtp_host,smtp_port)
server.ehlo()
server.starttls()
server.login(user,passw)
fromaddr = raw_input('Send mail by the name of: ')
tolist = raw_input('To: ').split()
sub = raw_input('Subject: ')
msg = email.MIMEMultipart.MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = email.Utils.COMMASPACE.join(tolist)
msg['Subject'] = sub
msg.attach(MIMEText(raw_input('Body: ')))
msg.attach(MIMEText('
sent via python', 'plain'))
server.sendmail(user,tolist,msg.as_string())
解决方案 9:
2022 年 12 月更新:
您需要使用应用密码来允许您的应用访问您的 Google 帐户。
使用应用程序密码登录:
应用密码是一个 16 位密码,可让安全性较低的应用或设备访问您的 Google 帐号。应用密码只能用于已开启两步验证的帐号。
此外,自 2022 年 5 月 30 日起,谷歌就不允许您的应用使用用户名(电子邮件地址)和密码访问您的谷歌帐户。所以现在,您需要用户名(电子邮件地址)和应用密码才能访问您的谷歌帐户。
安全性较低的应用和您的 Google 帐户:
为了帮助保障您的帐号安全,自 2022 年 5 月 30 日起,Google 不再支持使用要求您仅使用用户名和密码登录 Google 帐号的第三方应用或设备。
如何生成应用密码:
首先,点击9 个点中的“帐户”:
然后,从“安全”中单击“应用程序密码” 。 *在生成应用程序密码之前,请不要忘记打开两步验证,否则您无法生成应用程序密码:
然后,点击其他(自定义名称):
然后,输入你的应用程序名称,然后单击“生成”:
最后,您可以生成应用程序密码xylnudjdiwpojwzm
:
因此,您上面的应用程序密码的代码如下所示:
import smtplib
fromaddr = 'user_me@gmail.com'
toaddrs = 'user_you@gmail.com'
msg = 'Why,Oh why!'
username = 'user_me@gmail.com'
password = 'xylnudjdiwpojwzm' # Here
server = smtplib.SMTP('smtp.gmail.com:587')
server.starttls()
server.login(username,password)
server.sendmail(fromaddr, toaddrs, msg)
server.quit()
此外,上面的应用程序密码settings.py
在Django中如下所示:
# "settings.py"
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'myaccount@gmail.com'
EMAIL_HOST_PASSWORD = 'xylnudjdiwpojwzm' # Here
解决方案 10:
意识到通过 Python 发送电子邮件的很多事情是多么痛苦,因此我为它创建了一个广泛的库。它还预先配置了 Gmail(因此您不必记住 Gmail 的主机和端口):
from redmail import gmail
gmail.user_name = "you@gmail.com"
gmail.password = "<YOUR APPLICATION PASSWORD>"
# Send an email
gmail.send(
subject="An example email",
receivers=["recipient@example.com"],
text="Hi, this is text body.",
html="<h1>Hi, this is HTML body.</h1>"
)
当然你需要配置你的Gmail账户(不用担心,很简单):
设置两步验证(如果尚未设置)
创建应用程序密码
将应用程序密码输入到
gmail
对象中就完成了!
Red Mail 实际上功能相当全面(包括附件、嵌入图片、使用抄送和密送发送、使用 Jinja 模板等),应该可以满足您作为电子邮件发件人的所有需求。它还经过了充分的测试和记录。希望您觉得它有用。
安装:
pip install redmail
文档:https://red-mail.readthedocs.io/en/latest/
源代码:https://github.com/Miksus/red-mail
请注意,Gmail 不允许更改发件人。发件人地址始终是您。
解决方案 11:
在您的 Gmail 帐户上启用安全性较低的应用程序并使用(Python>=3.6):
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
gmailUser = 'XXXXX@gmail.com'
gmailPassword = 'XXXXX'
recipient = 'XXXXX@gmail.com'
message = f"""
Type your message here...
"""
msg = MIMEMultipart()
msg['From'] = f'"Your Name" <{gmailUser}>'
msg['To'] = recipient
msg['Subject'] = "Subject here..."
msg.attach(MIMEText(message))
try:
mailServer = smtplib.SMTP('smtp.gmail.com', 587)
mailServer.ehlo()
mailServer.starttls()
mailServer.ehlo()
mailServer.login(gmailUser, gmailPassword)
mailServer.sendmail(gmailUser, recipient, msg.as_string())
mailServer.close()
print ('Email sent!')
except:
print ('Something went wrong...')
解决方案 12:
现在有一个 gmail API,它允许您通过 REST 发送电子邮件、阅读电子邮件和创建草稿。与 SMTP 调用不同,它是非阻塞的,这对于在请求线程中发送电子邮件的基于线程的 Web 服务器(如 python Web 服务器)来说是一件好事。该 API 也非常强大。
当然,电子邮件应该交给非网络服务器队列,但有选择就更好了。
如果您拥有域中的 Google Apps 管理员权限,则设置起来最容易,因为这样您就可以向客户端授予全面权限。否则,您必须摆弄 OAuth 身份验证和权限。
以下是演示它的要点:
https://gist.github.com/timrichardson/1154e29174926e462b7a
解决方案 13:
@David 的回答很棒,这里是针对没有通用 try-except 的 Python 3 的:
def send_email(user, password, recipient, subject, body):
gmail_user = user
gmail_pwd = password
FROM = user
TO = recipient if type(recipient) is list else [recipient]
SUBJECT = subject
TEXT = body
# Prepare actual message
message = """From: %s
To: %s
Subject: %s
%s
""" % (FROM, ", ".join(TO), SUBJECT, TEXT)
server = smtplib.SMTP("smtp.gmail.com", 587)
server.ehlo()
server.starttls()
server.login(gmail_user, gmail_pwd)
server.sendmail(FROM, TO, message)
server.close()
解决方案 14:
似乎是老问题smtplib
。python2.7
一切正常。
更新:是的,server.ehlo()
也可以提供帮助。
解决方案 15:
这会对你有帮助。我用的是这个方法
首先,您必须从您的 Google 帐户激活“两步验证”。请按照以下步骤操作:
进入谷歌帐户-> “安全”标签(从左侧菜单)->找到“如何登录谷歌”,然后启用“两步验证”
点击“两步验证”,然后点击页面底部的“应用密码” ,然后点击“选择应用”,选择“其他(自定义名称)”,输入名称后点击生成。
保存屏幕上显示的密码。
我使用了下面的代码,您可以配置并使用它。
import os
from email.message import EmailMessage
import ssl
import smtplib
email_sender = 'mohsennavazani@gmail.com' #only gmail
email_password = 'Your password from section 3'
email_receiver = 'mohsennavazani@gmail.com' #any type of email
subject = 'check my website (Mohsennavazani.ir)'
body = """
Hello,
this is a test
"""
em = EmailMessage()
em['From'] = email_sender
em['To'] = email_receiver
em['Subject'] = subject
em.set_content(body)
#add a layer of security
context = ssl.create_default_context()
#sending the email
with smtplib.SMTP_SSL('smtp.gmail.com', 465, context=context) as smtp:
smtp.login(email_sender,email_password)
smtp.sendmail(email_sender,email_receiver, em.as_string())
运行代码片段Hide results展开片段
5-(可选)如果您需要向多个电子邮件地址发送电子邮件,您可以在最后一部分使用以下代码。
li = ["mohsennavazani@gmail.com", "sbu.ar.mohsen@gmail.com"]
with smtplib.SMTP_SSL('smtp.gmail.com',465,context=context) as smtp:
smtp.login(email_sender,email_password)
smtp.sendmail(email_sender,li, em.as_string())
运行代码片段Hide results展开片段
解决方案 16:
import smtplib
fromadd='from@gmail.com'
toadd='send@gmail.com'
msg='''hi,how r u'''
username='abc@gmail.com'
passwd='password'
try:
server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo()
server.starttls()
server.login(username,passwd)
server.sendmail(fromadd,toadd,msg)
print("Mail Send Successfully")
server.quit()
except:
print("Error:unable to send mail")
NOTE:https://www.google.com/settings/security/lesssecureapps that should be enabled
解决方案 17:
import smtplib
server = smtplib.SMTP('smtp.gmail.com', 587)
server.ehlo()
server.starttls()
server.login("fromaddress", "password")
msg = "HI!"
server.sendmail("fromaddress", "receiveraddress", msg)
server.quit()