smtplib and gmail - python script problems

2019-01-31 19:56发布

问题:

Here's my script:

#!/usr/bin/python

import smtplib
msg = 'Hello world.'

server = smtplib.SMTP('smtp.gmail.com',587) #port 465 or 587
server.ehlo()
server.starttls()
server.ehlo()
server.login('myname@gmail.com','mypass')
server.sendmail('myname@gmail.com','somename@somewhere.com',msg)
server.close()

I'm just trying to send an email from my gmail account. The script uses starttls because of gmail's requirement. I've tried this on two web hosts, 1and1 and webfaction. 1and1 gives me a 'connection refused' error and webfaction reports no error but just doesn't send the email. I can't see anything wrong with the script, so I'm thinking it might be related to the web hosts. Any thoughts and comments would be much appreciated.

EDIT: I turned on debug mode. From the output, it looks like it sent the message successfully...I just never receive it.

send: 'ehlo web65.webfaction.com\r\n'
reply: '250-mx.google.com at your service, [174.133.21.84]\r\n'
reply: '250-SIZE 35651584\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-STARTTLS\r\n'
reply: '250-ENHANCEDSTATUSCODES\r\n'
reply: '250 PIPELINING\r\n'
reply: retcode (250); Msg: mx.google.com at your service, [174.133.21.84]
SIZE 35651584
8BITMIME
STARTTLS
ENHANCEDSTATUSCODES
PIPELINING
send: 'STARTTLS\r\n'
reply: '220 2.0.0 Ready to start TLS\r\n'
reply: retcode (220); Msg: 2.0.0 Ready to start TLS
send: 'ehlo web65.webfaction.com\r\n'
reply: '250-mx.google.com at your service, [174.133.21.84]\r\n'
reply: '250-SIZE 35651584\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-AUTH LOGIN PLAIN\r\n'
reply: '250-ENHANCEDSTATUSCODES\r\n'
reply: '250 PIPELINING\r\n'
reply: retcode (250); Msg: mx.google.com at your service, [174.133.21.84]
SIZE 35651584
8BITMIME
AUTH LOGIN PLAIN
ENHANCEDSTATUSCODES
PIPELINING
send: 'AUTH PLAIN *****\r\n'
reply: '235 2.7.0 Accepted\r\n'
reply: retcode (235); Msg: 2.7.0 Accepted
send: 'mail FROM:<myname@gmail.com> size=12\r\n'
reply: '250 2.1.0 OK 4sm652580yxq.48\r\n'
reply: retcode (250); Msg: 2.1.0 OK 4sm652580yxq.48
send: 'rcpt TO:<myname@gmail.com>\r\n'
reply: '250 2.1.5 OK 4sm652580yxq.48\r\n'
reply: retcode (250); Msg: 2.1.5 OK 4sm652580yxq.48
send: 'data\r\n'
reply: '354  Go ahead 4sm652580yxq.48\r\n'
reply: retcode (354); Msg: Go ahead 4sm652580yxq.48
data: (354, 'Go ahead 4sm652580yxq.48')
send: 'Hello world.\r\n.\r\n'
reply: '250 2.0.0 OK 1240421143 4sm652580yxq.48\r\n'
reply: retcode (250); Msg: 2.0.0 OK 1240421143 4sm652580yxq.48
data: (250, '2.0.0 OK 1240421143 4sm652580yxq.48')

回答1:

I think that the GMail SMTP server does a reverse DNS lookup on the IP address that you connect from, and refuses the connection if no domain can be found. This is to avoid spammer from using their SMTP server as an open relay.



回答2:

Have you tried constructing a valid message?

from email.MIMEText import MIMEText

msg = MIMEText('body')
msg['Subject'] = 'subject'
msg['From'] = "..."
msg['Reply-to'] = "..."
msg['To'] = "..."


回答3:

I don't know if OP still cares about this answer, but having found myself here in an effort to troubleshoot a similar problem, hopefully someone else might find this useful. As it turns out, Google has changed the way that they allow their SMTP server to be used. You will want to check a couple of things:

  1. That you are using the same address you used to authenticate as the 'from' address. If I am not mistaken it used to be the case that you could put pretty much whatever you wanted in the from field, but for security purposes many SMTP host sites (including google) now restrict this to the address that has authenticated with them.

  2. Allow your account to be accessed by 'less secure apps' (read: apps we do not generate revenue from). To do that log into your account and navigate here: https://www.google.com/settings/security/lesssecureapps

  3. Use port 587 with tls. Not really sure why but I could never get port 465 to play nice.

Hope this helps somebody else out.



回答4:

Some self-promotion here, but I feel on a valid ground.

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

import yagmail
yag = yagmail.SMTP('myname@gmail.com')
yag.send('somename@somewhere.com', subject = None, contents = 'Hello')

Or a one liner:

yagmail.SMTP('myname@gmail.com').send('somename@somewhere.com', None, 'Hello world.')

What is nice is that I propose to use keyring to store your password, so you never have a risk of people seeing your password in your script.

You can set this up by running once in your interpreter:

import yagmail
yagmail.register("my@gmail.com", "mypassword")

and exit. Then you can just use:

import yagmail
yagmail.SMTP("my@gmail.com") # without password

If you add .yagmail with "my@gmail.com" in your home dir, then you can just do: yagmail.SMTP(), but that's rather pointless by now.

Warning: If you get serious about sending a lot of messages, better set up OAuth2, yagmail can help with that.

yagmail.SMTP("my@gmail.com", oauth2_file="/path/to/save/creds.json")

The first time ran, it will guide you through the process of getting OAuth2 credentials and store them in the file so that next time you don't need to do anything with it. Do you suspect someone found your credentials? They'll have limited permissions, but you better invalidate their credentials through gmail.

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



回答5:

save yourselves some headaches and use this:

http://mynthon.net/howto/-/python/python%20-%20logging.SMTPHandler-how-to-use-gmail-smtp-server.txt

Python SMTPHandler with GMail

Ss



回答6:

You'll need to check your "Sent" folder in GMail, as that's where a message sent from your account to your account will most probably show up.



回答7:

I went to the above mentioned link and had 3 different to addresses to send to but I received three emails to the same address and that being the #3 address.

http://mynthon.net/howto/-/python/python%20-%20logging.SMTPHandler-how-to-use-gmail-smtp-server.txt

import logging
import logging.handlers

class TlsSMTPHandler(logging.handlers.SMTPHandler):
def emit(self, record):
    """
    Emit a record.

    Format the record and send it to the specified addressees.
    """
    try:
        import smtplib
        import string # for tls add this line
        try:
            from email.utils import formatdate
        except ImportError:
            formatdate = self.date_time
        port = self.mailport
        if not port:
            port = smtplib.SMTP_PORT
        smtp = smtplib.SMTP(self.mailhost, port)
        msg = self.format(record)
        msg = "From: %s\r\nTo: %s\r\nSubject: %s\r\nDate: %s\r\n\r\n%s" % (
                        self.fromaddr,
                        string.join(self.toaddrs, ","),
                        self.getSubject(record),
                        formatdate(), msg)
        if self.username:
            smtp.ehlo() # for tls add this line
            smtp.starttls() # for tls add this line
            smtp.ehlo() # for tls add this line
            smtp.login(self.username, self.password)
        smtp.sendmail(self.fromaddr, self.toaddrs, msg)
        smtp.quit()
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        self.handleError(record)

logger = logging.getLogger()

gm = TlsSMTPHandler(("smtp.gmail.com", 587), 'myusername@gmail.com', ['address1@gmail.com', 'address2@gmail.com', 'address3@gmail.com'], 'unable to find Error!', ('myusername@gmail.com', 'mypassword'))
gm.setLevel(logging.ERROR)

logger.addHandler(gm)

try:
    1/0
except:
    logger.exception('It NO work for me!!-')


回答8:

It's works

'''
Created on 2017/11/27

@author: devuser
'''

import smtplib
from email.mime.text import MIMEText
from email.utils import formatdate

FROM_ADDRESS = 'sender@gmail.com'
MY_PASSWORD = 'password'
TO_ADDRESS = 'receiver@test.co.jp'
BCC = 'receiver2@test.net'
SUBJECT = 'GmailのSMTPサーバ経由'
BODY = 'pythonでメール送信'


def create_message(from_addr, to_addr, bcc_addrs, subject, body):
    msg = MIMEText(body)
    msg['Subject'] = subject
    msg['From'] = from_addr
    msg['To'] = to_addr
    msg['Bcc'] = bcc_addrs
    msg['Date'] = formatdate()
    return msg


def send(from_addr, to_addrs, msg):
    smtpobj = smtplib.SMTP('smtp.gmail.com', 587)
    smtpobj.ehlo()
    smtpobj.starttls()
    smtpobj.ehlo()
    smtpobj.login(FROM_ADDRESS, MY_PASSWORD)
    smtpobj.sendmail(from_addr, to_addrs, msg.as_string())
    smtpobj.close()


if __name__ == '__main__':

    to_addr = TO_ADDRESS
    subject = SUBJECT
    body = BODY

    msg = create_message(FROM_ADDRESS, to_addr, BCC, subject, body)
    send(FROM_ADDRESS, to_addr, msg)

https://qiita.com/okhrn/items/630a87ce1a44778bbeb1