标签归档:smtp

使用SMTP从Python发送邮件

问题:使用SMTP从Python发送邮件

我正在使用以下方法使用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()

I’m using the following method to send mail from Python using SMTP. Is it the right method to use or are there gotchas I’m missing ?

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()

回答 0

我使用的脚本非常相似。我将其张贴在此处,作为如何使用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

The script I use is quite similar; I post it here as an example of how to use the email.* modules to generate MIME messages; so this script can be easily modified to attach pictures, etc.

I rely on my ISP to add the date time header.

My ISP requires me to use a secure smtp connection to send mail, I rely on the smtplib module (downloadable at http://www1.cs.columbia.edu/~db2501/ssmtplib.py)

As in your script, the username and password, (given dummy values below), used to authenticate on the SMTP server, are in plain text in the source. This is a security weakness; but the best alternative depends on how careful you need (want?) to be about protecting these.

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

#! /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

回答 1

我通常使用的方法…没什么大的不同

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()

而已

The method I commonly use…not much different but a little bit

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()

That’s it


回答 2

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

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

Also if you want to do smtp auth with TLS as opposed to SSL then you just have to change the port (use 587) and do smtp.starttls(). This worked for me:

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

回答 3

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

The main gotcha I see is that you’re not handling any errors: .login() and .sendmail() both have documented exceptions that they can throw, and it seems like .connect() must have some way to indicate that it was unable to connect – probably an exception thrown by the underlying socket code.


回答 4

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

Make sure you don’t have any firewalls blocking SMTP. The first time I tried to send an email, it was blocked both by Windows Firewall and McAfee – took forever to find them both.


回答 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()

What about this?

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

以下代码对我来说很好用:

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/

following code is working fine for me:

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()

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


回答 7

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

You should make sure you format the date in the correct format – RFC2822.


回答 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()

The example code which i did for send mail using 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

查看所有这些宽大的答案?请允许我通过几行来自我推广。

导入并连接:

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。

See all those lenghty answers? Please allow me to self promote by doing it all in a couple of lines.

Import and Connect:

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

Then it is just a one-liner:

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

It will actually close when it goes out of scope (or can be closed manually). Furthermore, it will allow you to register your username in your keyring such that you do not have to write out your password in your script (it really bothered me prior to writing yagmail!)

For the package/installation, tips and tricks please look at git or pip, available for both Python 2 and 3.


回答 10

你可以那样做

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)

you can do like that

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)

回答 11

这是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)))

Here’s a working example for 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)))

回答 12

基于此示例,我做了以下功能:

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
        /programming/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:
                # /programming/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 -> /programming/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电子邮件(对于不支持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服务器,请启用对安全性较低的应用程序的临时访问或永久访问:

Based on this example I made following function:

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

if you pass only body then plain text mail will be sent, but if you pass html argument along with body argument, html email will be sent (with fallback to text content for email clients that don’t support html/mime types).

Example usage:

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"

Btw. If you want to use gmail as testing or production SMTP server, enable temp or permanent access to less secured apps:


如何通过Django发送电子邮件?

问题:如何通过Django发送电子邮件?

在我的中settings.py,我具有以下内容:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

# Host for sending e-mail.
EMAIL_HOST = 'localhost'

# Port for sending e-mail.
EMAIL_PORT = 1025

# Optional SMTP authentication information for EMAIL_HOST.
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False

我的电子邮件代码:

from django.core.mail import EmailMessage
email = EmailMessage('Hello', 'World', to=['user@gmail.com'])
email.send()

当然,如果通过设置调试服务器python -m smtpd -n -c DebuggingServer localhost:1025,则可以在终端中看到该电子邮件。

但是,实际上我该如何将电子邮件发送到user@gmail.com而不是发送到调试服务器?

阅读您的答案后,让我弄明白一点:

  1. 您不能使用localhost(简单的ubuntu pc)发送电子邮件吗?

  2. 我以为在django 1.3中send_mail()已经过时了,EmailMessage.send()取而代之的是?

In my settings.py, I have the following:

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

# Host for sending e-mail.
EMAIL_HOST = 'localhost'

# Port for sending e-mail.
EMAIL_PORT = 1025

# Optional SMTP authentication information for EMAIL_HOST.
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
EMAIL_USE_TLS = False

My email code:

from django.core.mail import EmailMessage
email = EmailMessage('Hello', 'World', to=['user@gmail.com'])
email.send()

Of course, if I setup a debugging server via python -m smtpd -n -c DebuggingServer localhost:1025, I can see the email in my terminal.

However, how do I actually send the email not to the debugging server but to user@gmail.com?

After reading your answers, let me get something straight:

  1. Can’t you use localhost(simple ubuntu pc) to send e-mails?

  2. I thought in django 1.3 send_mail() is somewhat deprecated and EmailMessage.send() is used instead?


回答 0

将电子邮件发送到真实的SMTP服务器。如果您不想建立自己的公司,则可以找到可以为您经营公司的公司,例如Google自己。

Send the email to a real SMTP server. If you don’t want to set up your own then you can find companies that will run one for you, such as Google themselves.


回答 1

我将Gmail用作Django的SMTP服务器。比处理postfix或任何其他服务器容易得多。我不从事电子邮件服务器的管理。

在settings.py中:

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'me@gmail.com'
EMAIL_HOST_PASSWORD = 'password'

注意:默认情况下,2016年Gmail不再允许这样做。您可以使用Sendgrid之类的外部服务,也可以按照Google的本教程来降低安全性,但可以选择以下选项:https : //support.google.com/accounts/answer/6010255

I use Gmail as my SMTP server for Django. Much easier than dealing with postfix or whatever other server. I’m not in the business of managing email servers.

In settings.py:

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'me@gmail.com'
EMAIL_HOST_PASSWORD = 'password'

NOTE: In 2016 Gmail is not allowing this anymore by default. You can either use an external service like Sendgrid, or you can follow this tutorial from Google to reduce security but allow this option: https://support.google.com/accounts/answer/6010255


回答 2

  1. 创建一个项目: django-admin.py startproject gmail
  2. 使用以下代码编辑settings.py:

    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_USE_TLS = True
    EMAIL_HOST = 'smtp.gmail.com'
    EMAIL_HOST_USER = 'youremail@gmail.com'
    EMAIL_HOST_PASSWORD = 'email_password'
    EMAIL_PORT = 587
  3. 运行交互模式: python manage.py shell

  4. 导入EmailMessage模块:

    from django.core.mail import EmailMessage
  5. 发送电子邮件:

    email = EmailMessage('Subject', 'Body', to=['your@email.com'])
    email.send()

有关更多信息,请检查send_mail文档中的EmailMessage功能。

Gmail更新

另外,如果您在通过gmail发送电子邮件时遇到问题,请记住从Google 查看本指南

在您的Google帐户设置中,转到 Security > Account permissions > Access for less secure apps并启用此选项。

启用两步验证后,还要为您的gmail创建一个应用专用密码

然后,您应该在设置中使用应用专用密码。因此,更改以下行:

    EMAIL_HOST_PASSWORD = 'your_email_app_specific_password'

另外,如果您有兴趣发送HTML电子邮件,请检查此

  1. Create a project: django-admin.py startproject gmail
  2. Edit settings.py with code below:

    EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
    EMAIL_USE_TLS = True
    EMAIL_HOST = 'smtp.gmail.com'
    EMAIL_HOST_USER = 'youremail@gmail.com'
    EMAIL_HOST_PASSWORD = 'email_password'
    EMAIL_PORT = 587
    
  3. Run interactive mode: python manage.py shell

  4. Import the EmailMessage module:

    from django.core.mail import EmailMessage
    
  5. Send the email:

    email = EmailMessage('Subject', 'Body', to=['your@email.com'])
    email.send()
    

For more informations, check send_mail and EmailMessage features in documents.

UPDATE for Gmail

Also if you have problems sending email via gmail remember to check this guides from google.

In your Google account settings, go to Security > Account permissions > Access for less secure apps and enable this option.

Also create an App specific password for your gmail after you’ve turned on 2-step-verification for it.

Then you should use app specific password in settings. So change the following line:

    EMAIL_HOST_PASSWORD = 'your_email_app_specific_password'

Also if you’re interested to send HTML email, check this out.


回答 3

我的网站位于Godaddy,我在同一网站上注册了一封私人电子邮件。这些是对我有用的设置:

在settings.py中:

EMAIL_HOST = 'mail.domain.com'
EMAIL_HOST_USER = 'abc@domain.com'
EMAIL_HOST_PASSWORD = 'abcdef'
DEFAULT_FROM_EMAIL = 'abc@domain.com'
SERVER_EMAIL = 'abc@domain.com'
EMAIL_PORT = 25
EMAIL_USE_TLS = False

在外壳中:

from django.core.mail import EmailMessage
email = EmailMessage('Subject', 'Body', to=['def@domain.com'])
email.send()

然后我得到“ 1”作为O / P,即成功。而且我也收到了邮件。:)

  • domain.com是什么意思?

My site is hosted on Godaddy and I have a private email registered on the same. These are the settings which worked for me:

In settings.py:

EMAIL_HOST = 'mail.domain.com'
EMAIL_HOST_USER = 'abc@domain.com'
EMAIL_HOST_PASSWORD = 'abcdef'
DEFAULT_FROM_EMAIL = 'abc@domain.com'
SERVER_EMAIL = 'abc@domain.com'
EMAIL_PORT = 25
EMAIL_USE_TLS = False

In shell:

from django.core.mail import EmailMessage
email = EmailMessage('Subject', 'Body', to=['def@domain.com'])
email.send()

Then I got “1” as the O/P i.e. Success. And I received the mail too. :)

  • What is the meaning of domain.com?

回答 4

对于Django 1.7版,如果上述解决方案不起作用,请尝试以下操作

settings.py中添加

#For email
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

EMAIL_USE_TLS = True

EMAIL_HOST = 'smtp.gmail.com'

EMAIL_HOST_USER = 'sender@gmail.com'

#Must generate specific password for your app in [gmail settings][1]
EMAIL_HOST_PASSWORD = 'app_specific_password'

EMAIL_PORT = 587

#This did the trick
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

最后一行完成了Django 1.7的技巧

For Django version 1.7, if above solutions dont work then try the following

in settings.py add

#For email
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

EMAIL_USE_TLS = True

EMAIL_HOST = 'smtp.gmail.com'

EMAIL_HOST_USER = 'sender@gmail.com'

#Must generate specific password for your app in [gmail settings][1]
EMAIL_HOST_PASSWORD = 'app_specific_password'

EMAIL_PORT = 587

#This did the trick
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER

The last line did the trick for django 1.7


回答 5

您需要使用smtp作为 settings.py中的后端

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

如果将后端用作控制台,则将在控制台中接收输出

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

还有下面的设置

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'urusername@gmail.com'
EMAIL_HOST_PASSWORD = 'password'

如果您为此使用gmail,请设置两步验证特定应用程序的密码,然后将该密码复制并粘贴到上面的EMAIL_HOST_PASSWORD值中。

You need to use smtp as backend in settings.py

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

If you use backend as console, you will receive output in console

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

And also below settings in addition

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'urusername@gmail.com'
EMAIL_HOST_PASSWORD = 'password'

If you are using gmail for this, setup 2-step verification and Application specific password and copy and paste that password in above EMAIL_HOST_PASSWORD value.


回答 6

我发现使用SendGrid是设置使用Django发送电子邮件的最简单方法。运作方式如下:

  1. 创建一个SendGrid帐户(并验证您的电子邮件)
  2. 将以下内容添加到您的settings.py EMAIL_HOST = 'smtp.sendgrid.net' EMAIL_HOST_USER = '<your sendgrid username>' EMAIL_HOST_PASSWORD = '<your sendgrid password>' EMAIL_PORT = 587 EMAIL_USE_TLS = True

一切准备就绪!

发送电子邮件:

from django.core.mail import send_mail
send_mail('<Your subject>', '<Your message>', 'from@example.com', ['to@example.com'])

如果您希望Django在出现500个内部服务器错误时向您发送电子邮件,请将以下内容添加到您的中settings.py

DEFAULT_FROM_EMAIL = 'your.email@example.com'
ADMINS = [('<Your name>', 'your.email@example.com')]

使用SendGrid发送电子邮件每月最多免费获得1.2万封电子邮件。

I found using SendGrid to be the easiest way to set up sending email with Django. Here’s how it works:

  1. Create a SendGrid account (and verify your email)
  2. Add the following to your settings.py: EMAIL_HOST = 'smtp.sendgrid.net' EMAIL_HOST_USER = '<your sendgrid username>' EMAIL_HOST_PASSWORD = '<your sendgrid password>' EMAIL_PORT = 587 EMAIL_USE_TLS = True

And you’re all set!

To send email:

from django.core.mail import send_mail
send_mail('<Your subject>', '<Your message>', 'from@example.com', ['to@example.com'])

If you want Django to email you whenever there’s a 500 internal server error, add the following to your settings.py:

DEFAULT_FROM_EMAIL = 'your.email@example.com'
ADMINS = [('<Your name>', 'your.email@example.com')]

Sending email with SendGrid is free up to 12k emails per month.


回答 7

我实际上是在Django之前完成的。打开一个合法的GMail帐户,然后在此处输入凭据。这是我的代码-

from email import Encoders
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart

def sendmail(to, subject, text, attach=[], mtype='html'):
    ok = True
    gmail_user = settings.EMAIL_HOST_USER
    gmail_pwd  = settings.EMAIL_HOST_PASSWORD

    msg = MIMEMultipart('alternative')

    msg['From']    = gmail_user
    msg['To']      = to
    msg['Cc']      = 'you@gmail.com'
    msg['Subject'] = subject

    msg.attach(MIMEText(text, mtype))

    for a in attach:
        part = MIMEBase('application', 'octet-stream')
        part.set_payload(open(attach, 'rb').read())
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition','attachment; filename="%s"' % os.path.basename(a))
        msg.attach(part)

    try:
        mailServer = smtplib.SMTP("smtp.gmail.com", 687)
        mailServer.ehlo()
        mailServer.starttls()
        mailServer.ehlo()
        mailServer.login(gmail_user, gmail_pwd)
        mailServer.sendmail(gmail_user, [to,msg['Cc']], msg.as_string())
        mailServer.close()
    except:
        ok = False
    return ok

I had actually done this from Django a while back. Open up a legitimate GMail account & enter the credentials here. Here’s my code –

from email import Encoders
from email.MIMEBase import MIMEBase
from email.MIMEText import MIMEText
from email.MIMEMultipart import MIMEMultipart

def sendmail(to, subject, text, attach=[], mtype='html'):
    ok = True
    gmail_user = settings.EMAIL_HOST_USER
    gmail_pwd  = settings.EMAIL_HOST_PASSWORD

    msg = MIMEMultipart('alternative')

    msg['From']    = gmail_user
    msg['To']      = to
    msg['Cc']      = 'you@gmail.com'
    msg['Subject'] = subject

    msg.attach(MIMEText(text, mtype))

    for a in attach:
        part = MIMEBase('application', 'octet-stream')
        part.set_payload(open(attach, 'rb').read())
        Encoders.encode_base64(part)
        part.add_header('Content-Disposition','attachment; filename="%s"' % os.path.basename(a))
        msg.attach(part)

    try:
        mailServer = smtplib.SMTP("smtp.gmail.com", 687)
        mailServer.ehlo()
        mailServer.starttls()
        mailServer.ehlo()
        mailServer.login(gmail_user, gmail_pwd)
        mailServer.sendmail(gmail_user, [to,msg['Cc']], msg.as_string())
        mailServer.close()
    except:
        ok = False
    return ok

回答 8

晚了,但是:

除了DEFAULT_FROM_EMAIL其他人提到的修复程序,允许安全性较低的应用访问该帐户外,我还必须以相关帐户的身份登录到https://accounts.google.com/DisplayUnlockCaptcha,以使Django最终通过身份验证。

我通过SSH隧道到达Web服务器的URL,以确保IP地址相同。我不确定这是否必要,但不会造成伤害。您可以这样操作:ssh -D 8080 -fN <username>@<host>,然后将Web浏览器设置localhost:8080为用作SOCKS代理。

Late, but:

In addition to the DEFAULT_FROM_EMAIL fix others have mentioned, and allowing less-secure apps to access the account, I had to navigate to https://accounts.google.com/DisplayUnlockCaptcha while signed in as the account in question to get Django to finally authenticate.

I went to that URL through a SSH tunnel to the web server to make sure the IP address was the same; I’m not totally sure if that’s necessary but it can’t hurt. You can do that like so: ssh -D 8080 -fN <username>@<host>, then set your web browser to use localhost:8080 as a SOCKS proxy.


回答 9

您可以使用“测试邮件服务器工具”来测试在您的计算机或本地主机上发送的电子邮件。Google并下载“测试邮件服务器工具”并进行设置。

然后在您的settings.py中:

EMAIL_BACKEND= 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_PORT = 25

从外壳:

from django.core.mail import send_mail
send_mail('subject','message','sender email',['receipient email'],    fail_silently=False)

You could use “Test Mail Server Tool” to test email sending on your machine or localhost. Google and Download “Test Mail Server Tool” and set it up.

Then in your settings.py:

EMAIL_BACKEND= 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'localhost'
EMAIL_PORT = 25

From shell:

from django.core.mail import send_mail
send_mail('subject','message','sender email',['receipient email'],    fail_silently=False)

回答 10

对于 SendGrid-Django具体而言:

SendGrid Django文档在这里

在以下位置设置这些变量

settings.py

EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_HOST_USER = 'sendgrid_username'
EMAIL_HOST_PASSWORD = 'sendgrid_password'
EMAIL_PORT = 587
EMAIL_USE_TLS = True

在views.py中

from django.core.mail import send_mail
send_mail('Subject here', 'Here is the message.', 'from@example.com', ['to@example.com'], fail_silently=False)

For SendGrid – Django Specifically:

SendGrid Django Docs here

Set these variables in

settings.py

EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_HOST_USER = 'sendgrid_username'
EMAIL_HOST_PASSWORD = 'sendgrid_password'
EMAIL_PORT = 587
EMAIL_USE_TLS = True

in views.py

from django.core.mail import send_mail
send_mail('Subject here', 'Here is the message.', 'from@example.com', ['to@example.com'], fail_silently=False)

如何使用python smtplib向多个收件人发送电子邮件?

问题:如何使用python smtplib向多个收件人发送电子邮件?

经过大量搜索后,我无法找到如何使用smtplib.sendmail发送给多个收件人的方法。问题是每次发送邮件时,邮件标题似乎都包含多个地址,但实际上只有第一个收件人会收到电子邮件。

问题似乎在于email.Message模块期望的smtplib.sendmail()功能与功能不同。

简而言之,要发送给多个收件人,您应该将标题设置为以逗号分隔的电子邮件地址的字符串。但是,该sendmail()参数to_addrs应为电子邮件地址列表。

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

msg = MIMEMultipart()
msg["Subject"] = "Example"
msg["From"] = "me@example.com"
msg["To"] = "malcom@example.com,reynolds@example.com,firefly@example.com"
msg["Cc"] = "serenity@example.com,inara@example.com"
body = MIMEText("example email body")
msg.attach(body)
smtp = smtplib.SMTP("mailhost.example.com", 25)
smtp.sendmail(msg["From"], msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
smtp.quit()

After much searching I couldn’t find out how to use smtplib.sendmail to send to multiple recipients. The problem was every time the mail would be sent the mail headers would appear to contain multiple addresses, but in fact only the first recipient would receive the email.

The problem seems to be that the email.Message module expects something different than the smtplib.sendmail() function.

In short, to send to multiple recipients you should set the header to be a string of comma delimited email addresses. The sendmail() parameter to_addrs however should be a list of email addresses.

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

msg = MIMEMultipart()
msg["Subject"] = "Example"
msg["From"] = "me@example.com"
msg["To"] = "malcom@example.com,reynolds@example.com,firefly@example.com"
msg["Cc"] = "serenity@example.com,inara@example.com"
body = MIMEText("example email body")
msg.attach(body)
smtp = smtplib.SMTP("mailhost.example.com", 25)
smtp.sendmail(msg["From"], msg["To"].split(",") + msg["Cc"].split(","), msg.as_string())
smtp.quit()

回答 0

确实有效,我花了大量时间尝试多种变体。

import smtplib
from email.mime.text import MIMEText

s = smtplib.SMTP('smtp.uk.xensource.com')
s.set_debuglevel(1)
msg = MIMEText("""body""")
sender = 'me@example.com'
recipients = ['john.doe@example.com', 'john.smith@example.co.uk']
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = ", ".join(recipients)
s.sendmail(sender, recipients, msg.as_string())

This really works, I spent a lot of time trying multiple variants.

import smtplib
from email.mime.text import MIMEText

s = smtplib.SMTP('smtp.uk.xensource.com')
s.set_debuglevel(1)
msg = MIMEText("""body""")
sender = 'me@example.com'
recipients = ['john.doe@example.com', 'john.smith@example.co.uk']
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = ", ".join(recipients)
s.sendmail(sender, recipients, msg.as_string())

回答 1

msg['To']需要是一个字符串:

msg['To'] = "a@b.com, b@b.com, c@b.com"

虽然recipientsin sendmail(sender, recipients, message)需要是一个列表:

sendmail("a@a.com", ["a@b.com", "b@b.com", "c@b.com"], "Howdy")

The msg['To'] needs to be a string:

msg['To'] = "a@b.com, b@b.com, c@b.com"

While the recipients in sendmail(sender, recipients, message) needs to be a list:

sendmail("a@a.com", ["a@b.com", "b@b.com", "c@b.com"], "Howdy")

回答 2

您需要了解电子邮件的可见地址和投递之间的区别。

msg["To"]本质上是印刷在信件上的东西。它实际上没有任何作用。除了您的电子邮件客户端(与常规邮递员一样)之外,您还将假定这是您要将电子邮件发送给的人。

但是,实际交付可能会大不相同。所以你可以将电子邮件(或副本)放入完全不同的人的邮箱中。

有多种原因。例如转发。的To:头字段不上转发更改,但是,电子邮件被放入不同的邮箱。

smtp.sendmail现在,该命令将负责实际交付。email.Message仅是信件的内容,而不是交货的内容。

在低级中SMTP,您需要一个个地给接收者一个地址,这就是为什么地址列表(不包括名称!)才是明智的API的原因。

对于标题,它还可以包含例如名称,例如To: First Last <email@addr.tld>, Other User <other@mail.tld>因此,不建议您使用代码示例,因为它将无法传递此邮件,因为仅将其拆分给,您,您仍然没有有效的地址!

You need to understand the difference between the visible address of an email, and the delivery.

msg["To"] is essentially what is printed on the letter. It doesn’t actually have any effect. Except that your email client, just like the regular post officer, will assume that this is who you want to send the email to.

The actual delivery however can work quite different. So you can drop the email (or a copy) into the post box of someone completely different.

There are various reasons for this. For example forwarding. The To: header field doesn’t change on forwarding, however the email is dropped into a different mailbox.

The smtp.sendmail command now takes care of the actual delivery. email.Message is the contents of the letter only, not the delivery.

In low-level SMTP, you need to give the receipients one-by-one, which is why a list of adresses (not including names!) is the sensible API.

For the header, it can also contain for example the name, e.g. To: First Last <email@addr.tld>, Other User <other@mail.tld>. Your code example therefore is not recommended, as it will fail delivering this mail, since just by splitting it on , you still not not have the valid adresses!


回答 3

这个对我有用。

import smtplib
from email.mime.text import MIMEText

s = smtplib.SMTP('smtp.uk.xensource.com')
s.set_debuglevel(1)
msg = MIMEText("""body""")
sender = 'me@example.com'
recipients = 'john.doe@example.com,john.smith@example.co.uk'
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = recipients
s.sendmail(sender, recipients.split(','), msg.as_string())

It works for me.

import smtplib
from email.mime.text import MIMEText

s = smtplib.SMTP('smtp.uk.xensource.com')
s.set_debuglevel(1)
msg = MIMEText("""body""")
sender = 'me@example.com'
recipients = 'john.doe@example.com,john.smith@example.co.uk'
msg['Subject'] = "subject line"
msg['From'] = sender
msg['To'] = recipients
s.sendmail(sender, recipients.split(','), msg.as_string())

回答 4

我尝试了下面的方法,它就像一个魅力:)

rec_list =  ['first@example.com', 'second@example.com']
rec =  ', '.join(rec_list)

msg['To'] = rec

send_out = smtplib.SMTP('localhost')
send_out.sendmail(me, rec_list, msg.as_string())

I tried the below and it worked like a charm :)

rec_list =  ['first@example.com', 'second@example.com']
rec =  ', '.join(rec_list)

msg['To'] = rec

send_out = smtplib.SMTP('localhost')
send_out.sendmail(me, rec_list, msg.as_string())

回答 5

所以实际上问题是SMTP.sendmail和email.MIMEText需要两个不同的东西。

email.MIMEText设置电子邮件正文的“ To:”标头。它仅用于向另一端的人显示结果,并且像所有电子邮件头一样,必须为单个字符串。(请注意,它实际上与实际收到邮件的人没有任何关系。)

另一方面,SMTP.sendmail为SMTP协议设置邮件的“信封”。它需要一个Python字符串列表,每个字符串都有一个地址。

因此,您需要做的就是合并收到的两份回复。将msg [‘To’]设置为单个字符串,但将原始列表传递给sendmail:

emails = ['a.com','b.com', 'c.com']
msg['To'] = ', '.join( emails ) 
....
s.sendmail( msg['From'], emails, msg.as_string())

So actually the problem is that SMTP.sendmail and email.MIMEText need two different things.

email.MIMEText sets up the “To:” header for the body of the e-mail. It is ONLY used for displaying a result to the human being at the other end, and like all e-mail headers, must be a single string. (Note that it does not actually have to have anything to do with the people who actually receive the message.)

SMTP.sendmail, on the other hand, sets up the “envelope” of the message for the SMTP protocol. It needs a Python list of strings, each of which has a single address.

So, what you need to do is COMBINE the two replies you received. Set msg[‘To’] to a single string, but pass the raw list to sendmail:

emails = ['a.com','b.com', 'c.com']
msg['To'] = ', '.join( emails ) 
....
s.sendmail( msg['From'], emails, msg.as_string())

回答 6

我想出了这个可导入的模块功能。在此示例中,它使用gmail电子邮件服务器。它分为标题和消息,因此您可以清楚地看到发生了什么:

import smtplib

def send_alert(subject=""):

    to = ['email@one.com', 'email2@another_email.com', 'a3rd@email.com']
    gmail_user = 'me@gmail.com'
    gmail_pwd = 'my_pass'
    smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
    smtpserver.ehlo()
    smtpserver.starttls()
    smtpserver.ehlo
    smtpserver.login(gmail_user, gmail_pwd)
    header = 'To:' + ", ".join(to) + '\n' + 'From: ' + gmail_user + '\n' + 'Subject: ' + subject + '\n'
    msg = header + '\n' + subject + '\n\n'
    smtpserver.sendmail(gmail_user, to, msg)
    smtpserver.close()

I came up with this importable module function. It uses the gmail email server in this example. Its split into header and message so you can clearly see whats going on:

import smtplib

def send_alert(subject=""):

    to = ['email@one.com', 'email2@another_email.com', 'a3rd@email.com']
    gmail_user = 'me@gmail.com'
    gmail_pwd = 'my_pass'
    smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
    smtpserver.ehlo()
    smtpserver.starttls()
    smtpserver.ehlo
    smtpserver.login(gmail_user, gmail_pwd)
    header = 'To:' + ", ".join(to) + '\n' + 'From: ' + gmail_user + '\n' + 'Subject: ' + subject + '\n'
    msg = header + '\n' + subject + '\n\n'
    smtpserver.sendmail(gmail_user, to, msg)
    smtpserver.close()

回答 7

几个月前我弄清楚了,然后发表了博客。摘要是:

如果要使用smtplib向多个收件人发送电子邮件,请使用email.Message.add_header('To', eachRecipientAsString)添加它们,然后在调用sendmail方法时,use email.Message.get_all('To')将消息发送给所有收件人。抄送和密件抄送收件人的同上。

I figured this out a few months back and blogged about it. The summary is:

If you want to use smtplib to send email to multiple recipients, use email.Message.add_header('To', eachRecipientAsString) to add them, and then when you invoke the sendmail method, use email.Message.get_all('To') send the message to all of them. Ditto for Cc and Bcc recipients.


回答 8

下面的解决方案为我工作。它成功地将电子邮件发送给多个收件人,包括“抄送”和“密件抄送”。

toaddr = ['mailid_1','mailid_2']
cc = ['mailid_3','mailid_4']
bcc = ['mailid_5','mailid_6']
subject = 'Email from Python Code'
fromaddr = 'sender_mailid'
message = "\n  !! Hello... !!"

msg['From'] = fromaddr
msg['To'] = ', '.join(toaddr)
msg['Cc'] = ', '.join(cc)
msg['Bcc'] = ', '.join(bcc)
msg['Subject'] = subject

s.sendmail(fromaddr, (toaddr+cc+bcc) , message)

The solution below worked for me. It successfully sends an email to multiple recipients, including “CC” and “BCC.”

toaddr = ['mailid_1','mailid_2']
cc = ['mailid_3','mailid_4']
bcc = ['mailid_5','mailid_6']
subject = 'Email from Python Code'
fromaddr = 'sender_mailid'
message = "\n  !! Hello... !!"

msg['From'] = fromaddr
msg['To'] = ', '.join(toaddr)
msg['Cc'] = ', '.join(cc)
msg['Bcc'] = ', '.join(bcc)
msg['Subject'] = subject

s.sendmail(fromaddr, (toaddr+cc+bcc) , message)

回答 9

那么,在方法本asnwer方法并没有为我工作。我不知道,也许这是Python3(我正在使用3.4版本)或gmail相关问题,但是经过一番尝试之后,对我有用的解决方案是

s.send_message(msg)

代替

s.sendmail(sender, recipients, msg.as_string())

Well, the method in this asnwer method did not work for me. I don’t know, maybe this is a Python3 (I am using the 3.4 version) or gmail related issue, but after some tries, the solution that worked for me, was the line

s.send_message(msg)

instead of

s.sendmail(sender, recipients, msg.as_string())

回答 10

我使用python 3.6,以下代码对我有用

email_send = 'xxxxx@xxx.xxx,xxxx@xxx.xxx'
server.sendmail(email_user,email_send.split(','),text)    

I use python 3.6 and the following code works for me

email_send = 'xxxxx@xxx.xxx,xxxx@xxx.xxx'
server.sendmail(email_user,email_send.split(','),text)    

回答 11

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def sender(recipients): 

    body = 'Your email content here'
    msg = MIMEMultipart()

    msg['Subject'] = 'Email Subject'
    msg['From'] = 'your.email@gmail.com'
    msg['To'] = (', ').join(recipients.split(','))

    msg.attach(MIMEText(body,'plain'))

    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login('your.email@gmail.com', 'yourpassword')
    server.send_message(msg)
    server.quit()

if __name__ == '__main__':
    sender('email_1@domain.com,email_2@domain.com')

它仅对我有用send_message函数,并在列表中使用接收函数python 3.6中的join函数。

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

def sender(recipients): 

    body = 'Your email content here'
    msg = MIMEMultipart()

    msg['Subject'] = 'Email Subject'
    msg['From'] = 'your.email@gmail.com'
    msg['To'] = (', ').join(recipients.split(','))

    msg.attach(MIMEText(body,'plain'))

    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    server.login('your.email@gmail.com', 'yourpassword')
    server.send_message(msg)
    server.quit()

if __name__ == '__main__':
    sender('email_1@domain.com,email_2@domain.com')

It only worked for me with send_message function and using the join function in the list whith recipients, python 3.6.


回答 12

您可以在文本文件上写收件人电子邮件时尝试使用此方法

from email.mime.text import MIMEText
from email.header import Header
import smtplib

f =  open('emails.txt', 'r').readlines()
for n in f:
     emails = n.rstrip()
server = smtplib.SMTP('smtp.uk.xensource.com')
server.ehlo()
server.starttls()
body = "Test Email"
subject = "Test"
from = "me@example.com"
to = emails
msg = MIMEText(body,'plain','utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] =  Header(from, 'utf-8')
msg['To'] = Header(to, 'utf-8')
text = msg.as_string()
try:
   server.send(from, emails, text)
   print('Message Sent Succesfully')
except:
   print('There Was An Error While Sending The Message')

you can try this when you write the recpient emails on a text file

from email.mime.text import MIMEText
from email.header import Header
import smtplib

f =  open('emails.txt', 'r').readlines()
for n in f:
     emails = n.rstrip()
server = smtplib.SMTP('smtp.uk.xensource.com')
server.ehlo()
server.starttls()
body = "Test Email"
subject = "Test"
from = "me@example.com"
to = emails
msg = MIMEText(body,'plain','utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] =  Header(from, 'utf-8')
msg['To'] = Header(to, 'utf-8')
text = msg.as_string()
try:
   server.send(from, emails, text)
   print('Message Sent Succesfully')
except:
   print('There Was An Error While Sending The Message')

如何使用Python以提供者的身份通过Gmail发送电子邮件?

问题:如何使用Python以提供者的身份通过Gmail发送电子邮件?

我正在尝试使用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()

I am trying to send email (Gmail) using python, but I am getting following error.

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.

The Python script is the following.

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()

回答 0

您需要先说一下EHLO才能直接进入STARTTLS

server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo()
server.starttls()

此外,你应该真正创造From:To:以及Subject:邮件标题,一个空行,并使用从邮件正文中分离出来CRLF作为EOL标志。

例如

msg = "\r\n".join([
  "From: user_me@gmail.com",
  "To: user_you@gmail.com",
  "Subject: Just a message",
  "",
  "Why, oh why"
  ])

You need to say EHLO before just running straight into STARTTLS:

server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo()
server.starttls()

Also you should really create From:, To: and Subject: message headers, separated from the message body by a blank line and use CRLF as EOL markers.

E.g.

msg = "\r\n".join([
  "From: user_me@gmail.com",
  "To: user_you@gmail.com",
  "Subject: Just a message",
  "",
  "Why, oh why"
  ])

回答 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\nTo: %s\nSubject: %s\n\n%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'
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\nTo: %s\nSubject: %s\n\n%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"

if you want to use Port 465 you have to create an SMTP_SSL object:

# 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

我遇到了类似的问题,偶然发现了这个问题。我收到SMTP身份验证错误,但我的用户名/密码正确。这是修复它的原因。我读到这个:

https://support.google.com/accounts/answer/6010255

简而言之,Google不允许您通过smtplib登录,因为它已将这种登录标记为“安全性较低”,因此您要做的就是在登录google帐户时转到此链接,并允许访问:

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\n5.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\n5.7.9 https://support.google.com/mail/bin/answer.py?answer=78754 qo11sm4014232igb.17 - gsmtp')

启用“ lesssecureapps”后,去喝杯咖啡,回来,然后再次尝试“ DisplayUnlockCaptcha”链接。根据用户的经验,更改可能最多需要一个小时才能生效。然后再次尝试登录过程。

I ran into a similar problem and stumbled on this question. I got an SMTP Authentication Error but my user name / pass was correct. Here is what fixed it. I read this:

https://support.google.com/accounts/answer/6010255

In a nutshell, google is not allowing you to log in via smtplib because it has flagged this sort of login as “less secure”, so what you have to do is go to this link while you’re logged in to your google account, and allow the access:

https://www.google.com/settings/security/lesssecureapps

Once that is set (see my screenshot below), it should work.

Login now works:

smtpserver = smtplib.SMTP("smtp.gmail.com", 587)
smtpserver.ehlo()
smtpserver.starttls()
smtpserver.ehlo()
smtpserver.login('me@gmail.com', 'me_pass')

Response after change:

(235, '2.7.0 Accepted')

Response prior:

smtplib.SMTPAuthenticationError: (535, '5.7.8 Username and Password not accepted. Learn more at\n5.7.8 http://support.google.com/mail/bin/answer.py?answer=14257 g66sm2224117qgf.37 - gsmtp')

Still not working? If you still get the SMTPAuthenticationError but now the code is 534, its because the location is unknown. Follow this link:

https://accounts.google.com/DisplayUnlockCaptcha

Click continue and this should give you 10 minutes for registering your new app. So proceed to doing another login attempt now and it should work.

UPDATE: This doesn’t seem to work right away you may be stuck for a while getting this error in smptlib:

235 == 'Authentication successful'
503 == 'Error: already authenticated'

The message says to use the browser to sign in:

SMTPAuthenticationError: (534, '5.7.9 Please log in with your web browser and then try again. Learn more at\n5.7.9 https://support.google.com/mail/bin/answer.py?answer=78754 qo11sm4014232igb.17 - gsmtp')

After enabling ‘lesssecureapps’, go for a coffee, come back, and try the ‘DisplayUnlockCaptcha’ link again. From user experience, it may take up to an hour for the change to kick in. Then try the sign-in process again.


回答 3

你对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 = "\r\n".join(headers)
        self.session.sendmail(
            self.email,
            self.email,
            headers + "\r\n\r\n" + body)


gm = Gmail('Your Email', 'Password')

gm.send_message('Subject', 'Message')

You down with 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 = "\r\n".join(headers)
        self.session.sendmail(
            self.email,
            self.email,
            headers + "\r\n\r\n" + body)


gm = Gmail('Your Email', 'Password')

gm.send_message('Subject', 'Message')

回答 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 = "Where are all my Robot Women at?"
sent_body = ("Hey, what's up? friend!\n\n"
             "I hope you have been well!\n"
             "\n"
             "Cheers,\n"
             "Jay\n")

email_text = """\
From: %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!\n\n" % exception)

因此,如果成功,将看到如下图像:

我通过向自己发送电子邮件和向自己发送电子邮件进行了测试。

注意:我的帐户启用了两步验证。应用密码与此配合使用!(对于gmail smtp设置,您必须转到https://support.google.com/accounts/answer/185833?hl=zh_CN并执行以下步骤)

此设置不适用于启用了两步验证的帐户。此类帐户需要特定于应用程序的密码,以降低安全性。

This Works

Create Gmail APP Password!

After you create that then create a file called sendgmail.py

Then add this code:

#!/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 = "Where are all my Robot Women at?"
sent_body = ("Hey, what's up? friend!\n\n"
             "I hope you have been well!\n"
             "\n"
             "Cheers,\n"
             "Jay\n")

email_text = """\
From: %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!\n\n" % exception)

So, if you are successful, will see an image like this:

I tested by sending an email from and to myself.

Note: I have 2-Step Verification enabled on my account. App Password works with this! (for gmail smtp setup, you must go to https://support.google.com/accounts/answer/185833?hl=en and follow the below steps)

This setting is not available for accounts with 2-Step Verification enabled. Such accounts require an application-specific password for less secure apps access.


回答 5

您可以在这里找到它: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('\nsent via python', 'plain'))
server.sendmail(user,tolist,msg.as_string())

You can find it here: 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('\nsent via python', 'plain'))
server.sendmail(user,tolist,msg.as_string())

回答 6

没有直接关系,但仍然值得指出的是,我的程序包试图使发送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!')

对于软件包/安装,请查看gitpip,它们可用于Python 2和3。

Not directly related but still worth pointing out is that my package tries to make sending gmail messages really quick and painless. It also tries to maintain a list of errors and tries to point to the solution immediately.

It would literally only need this code to do exactly what you wrote:

import yagmail
yag = yagmail.SMTP('user_me@gmail.com')
yag.send('user_you@gmail.com', 'Why,Oh why!')

Or a one liner:

yagmail.SMTP('user_me@gmail.com').send('user_you@gmail.com', 'Why,Oh why!')

For the package/installation please look at git or pip, available for both Python 2 and 3.


回答 7

这是一个Gmail API示例。尽管更复杂,但这是我发现的唯一一种在2019年有效的方法。该示例摘自并修改自:

https://developers.google.com/gmail/api/guides/sending

您需要通过其网站使用Google API接口创建一个项目。接下来,您需要为您的应用启用GMAIL API。创建凭据,然后下载这些凭据,将其另存为凭据.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()

Here is a Gmail API example. Although more complicated, this is the only method I found that works in 2019. This example was taken and modified from:

https://developers.google.com/gmail/api/guides/sending

You’ll need create a project with Google’s API interfaces through their website. Next you’ll need to enable the GMAIL API for your app. Create credentials and then download those creds, save it as 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()

回答 8

现在有一个gmail API,可让您通过REST发送电子邮件,阅读电子邮件和创建草稿。与SMTP调用不同,它是非阻塞的,这对于基于线程的Web服务器在请求线程中发送电子邮件(例如python Web服务器)可能是一件好事。该API也非常强大。

  • 当然,应该将电子邮件传递到非Web服务器队列,但是有选项很高兴。

如果您对域具有Google Apps管理员权限,那么设置起来最容易,因为这样您就可以授予客户一揽子许可。否则,您必须摆弄OAuth身份验证和权限。

这是一个证明它的要点:

https://gist.github.com/timrichardson/1154e29174926e462b7a

There is a gmail API now, which lets you send email, read email and create drafts via REST. Unlike the SMTP calls, it is non-blocking which can be a good thing for thread-based webservers sending email in the request thread (like python webservers). The API is also quite powerful.

  • Of course, email should be handed off to a non-webserver queue, but it’s nice to have options.

It’s easiest to setup if you have Google Apps administrator rights on the domain, because then you can give blanket permission to your client. Otherwise you have to fiddle with OAuth authentication and permission.

Here is a gist demonstrating it:

https://gist.github.com/timrichardson/1154e29174926e462b7a


回答 9

@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\nTo: %s\nSubject: %s\n\n%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()

great answer from @David, here is for Python 3 without the generic try-except:

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\nTo: %s\nSubject: %s\n\n%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()

回答 10

在您的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...')

Enable less secure apps on your gmail account and use (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...')

回答 11

好像是老问题了smtplib。在python2.7一切正常。

更新:是的,server.ehlo()也可以提供帮助。

Seems like problem of the old smtplib. In python2.7 everything works fine.

Update: Yep, server.ehlo() also could help.


回答 12

    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
    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

回答 13

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()
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()