python使用smtp库发送邮件

python smtp发邮件

开发一个日志扫描工具,用于扫描报错日志,并打包成邮件,发送到邮箱。
例子:

#!/usr/bin/env python  
# coding=utf-8  
from smtplib import SMTP  
from email import MIMEText  
from email import Header  
from os.path import getsize  
from sys import exit  
from re import compile, IGNORECASE  
#定义主机 帐号 密码 收件人 邮件主题  
smtpserver = '10.0.10.191'  
user = 'cxyblog'  
password = '*******'  
sender = 'cxyblog@163.com'  
receiver = ('xiaozi@163.com','收件人',)  
subject = u'Web服务器Tomcat日志错误信息'  
From = u'xxx Web服务器'  
To = u'服务器管理员'  
  
#发送邮件函数  
def send_mail(error):  
    #定义邮件的头部信息  
    header = Header.Header  
    msg = MIMEText.MIMEText(error,'plain','utf-8')  
    msg['From'] = header(From)  
    msg['To'] = header(To)  
    msg['Subject'] = header(subject+'
')  
    #连接SMTP服务器,然后发送信息  
    smtp = SMTP(smtpserver)  
    smtp.login(user, password)  
    smtp.sendmail(sender, receiver, msg.as_string())  
    smtp.close()  
      
send_mail("hi hello")  

代码使用说明:
1,user和password在调用163等邮箱时,user是自己的邮箱,senser也是自己的邮箱。
2,在公司内部邮件系统中,这个login的user,可能是其他的账户。sender,才是你自己的邮箱。

 

这段程序测试是通不过的,不过下面这个程序貌似更好.

  1. #!/usr/bin/env python   
  2. # coding:utf-8   
  3. import email   
  4. import smtplib   
  5. class Mailer:   
  6.     def __init__(self, smtp_host, smtp_user, smtp_passwd, smtp_port = 25) :   
  7.         self.smtp_host = smtp_host   
  8.         self.smtp_user = smtp_user   
  9.         self.smtp_passwd = smtp_passwd   
  10.         self.smtp_port = smtp_port   
  11.         self.mail = email.MIMEMultipart.MIMEMultipart('related')   
  12.         self.alter = email.MIMEMultipart.MIMEMultipart('alternative')   
  13.         self.mail.attach(self.alter)   
  14.         self.attachments = []   
  15.     def mailfrom(self, mail_from) :   
  16.         self._from = mail_from   
  17.         self.mail['from'] = mail_from   
  18.     def mailto(self, mail_to) :   
  19.         """  
  20.         mail_to : comma separated emails  
  21.         """  
  22.         self._to = mail_to   
  23.         if type(mail_to) == list:   
  24.             self.mail['to'] = ','.join(mail_to)   
  25.         elif type(mail_to) == str :   
  26.             self.mail['to'] = mail_to   
  27.         else :   
  28.             raise Exception('invalid mail to')   
  29.     def mailsubject(self, mail_subject) :   
  30.         self.mail['subject'] = mail_subject   
  31.     def text_body(self, body, encoding = 'utf-8') :   
  32.         self.alter.attach(email.MIMEText.MIMEText(body, 'plain', encoding))   
  33.     def html_body(self, body, encoding = 'utf-8') :   
  34.         self.alter.attach(email.MIMEText.MIMEText(body, 'html', encoding))   
  35.     def addattach(self, filepath, mime_type = 'octect-stream', rename = None) :   
  36.         import os   
  37.         f = open(filepath, 'rb')   
  38.         filecontent = f.read()   
  39.         f.close()   
  40.         mb = email.MIMEBase.MIMEBase('application', mime_type)   
  41.         mb.set_payload(filecontent)   
  42.         email.Encoders.encode_base64(mb)   
  43.         fn = os.path.basename(filepath)   
  44.         mb.add_header('Content-Disposition''attachment', filename = rename or fn)   
  45.         self.mail.attach(mb)   
  46.     def send(self):   
  47.         self.mail['Date'] = email.Utils.formatdate( )   
  48.         smtp = False  
  49.         try:   
  50.             smtp = smtplib.SMTP()   
  51.             smtp.set_debuglevel(1)   
  52.             smtp.connect(self.smtp_host, self.smtp_port)   
  53.             smtp.login(self.smtp_user, self.smtp_passwd)   
  54.             smtp.sendmail(self._from, self._to, self.mail.as_string())   
  55.             return  True  
  56.         except Exception, e:   
  57.             import traceback   
  58.             print traceback.format_exc()   
  59.             return False  
  60.         #finally :   
  61.         smtp and smtp.quit()   
  62. def get_mailer() :   
  63.     mailer = Mailer(, , )#smtp,user,pwd   
  64.     mailer.mailfrom('')#from email   
  65.     return mailer   
  66. if __name__ == '__main__':   
  67.     mailer = get_mailer()   
  68.        
  69.     import sys   
  70.     #mailto = sys.argv[1]   
  71.     #subject = sys.argv[2]   
  72.     #body = sys.stdin.read()   
  73.     #mailer.mailto(mailto)   
  74.     #mailer.mailsubject(subject)   
  75.     #mailer.html_body(body)   
  76.     #if len(sys.argv) == 4 :   
  77.     #    mailer.addattach(sys.argv[3])   
  78.     #mailer.send()   
  79.        
  80.     mailto = 'so@gmail.com'  
  81.     subject = 'Daily Report'  
  82.     body = 'Hello'  
  83.     mailer.mailto(mailto)   
  84.     mailer.mailsubject(subject)   
  85.     mailer.html_body(body)   
  86.     #if len(sys.argv) == 4 :   
  87.     mailer.addattach('318110214911a041c0ed077f0.xls')   
  88.     mailer.send()  
#!/usr/bin/env python
# coding:utf-8
import email
import smtplib
class Mailer:
    def __init__(self, smtp_host, smtp_user, smtp_passwd, smtp_port = 25) :
        self.smtp_host = smtp_host
        self.smtp_user = smtp_user
        self.smtp_passwd = smtp_passwd
        self.smtp_port = smtp_port
        self.mail = email.MIMEMultipart.MIMEMultipart('related')
        self.alter = email.MIMEMultipart.MIMEMultipart('alternative')
        self.mail.attach(self.alter)
        self.attachments = []
    def mailfrom(self, mail_from) :
        self._from = mail_from
        self.mail['from'] = mail_from
    def mailto(self, mail_to) :
        """
        mail_to : comma separated emails
        """
        self._to = mail_to
        if type(mail_to) == list:
            self.mail['to'] = ','.join(mail_to)
        elif type(mail_to) == str :
            self.mail['to'] = mail_to
        else :
            raise Exception('invalid mail to')
    def mailsubject(self, mail_subject) :
        self.mail['subject'] = mail_subject
    def text_body(self, body, encoding = 'utf-8') :
        self.alter.attach(email.MIMEText.MIMEText(body, 'plain', encoding))
    def html_body(self, body, encoding = 'utf-8') :
        self.alter.attach(email.MIMEText.MIMEText(body, 'html', encoding))
    def addattach(self, filepath, mime_type = 'octect-stream', rename = None) :
        import os
        f = open(filepath, 'rb')
        filecontent = f.read()
        f.close()
        mb = email.MIMEBase.MIMEBase('application', mime_type)
        mb.set_payload(filecontent)
        email.Encoders.encode_base64(mb)
        fn = os.path.basename(filepath)
        mb.add_header('Content-Disposition', 'attachment', filename = rename or fn)
        self.mail.attach(mb)
    def send(self):
        self.mail['Date'] = email.Utils.formatdate( )
        smtp = False
        try:
            smtp = smtplib.SMTP()
            smtp.set_debuglevel(1)
            smtp.connect(self.smtp_host, self.smtp_port)
            smtp.login(self.smtp_user, self.smtp_passwd)
            smtp.sendmail(self._from, self._to, self.mail.as_string())
            return  True
        except Exception, e:
            import traceback
            print traceback.format_exc()
            return False
        #finally :
        smtp and smtp.quit()
def get_mailer() :
    mailer = Mailer(, , )#smtp,user,pwd
    mailer.mailfrom('')#from email
    return mailer
if __name__ == '__main__':
    mailer = get_mailer()
    
    import sys
    #mailto = sys.argv[1]
    #subject = sys.argv[2]
    #body = sys.stdin.read()
    #mailer.mailto(mailto)
    #mailer.mailsubject(subject)
    #mailer.html_body(body)
    #if len(sys.argv) == 4 :
    #    mailer.addattach(sys.argv[3])
    #mailer.send()
    
    mailto = 'so@gmail.com'
    subject = 'Daily Report'
    body = 'Hello'
    mailer.mailto(mailto)
    mailer.mailsubject(subject)
    mailer.html_body(body)
    #if len(sys.argv) == 4 :
    mailer.addattach('318110214911a041c0ed077f0.xls')
    mailer.send()



这部分程序在发送向126,gmail的时候是成功的。但是公司连接的是国外的VPN,再连接的smtp

一下是debug的内容
connect: (************, 25)-----hostname
connect: (***********, 25)------ip
reply: '220 *********************************************************\r\n'
reply: retcode (220); Msg: *********************************************************
connect: *********************************************************
send: 'ehlo [**********]\r\n'
reply: '250-************ Hello [*********]\r\n'
reply: '250-SIZE 29360128\r\n'
reply: '250-PIPELINING\r\n'
reply: '250-DSN\r\n'
reply: '250-ENHANCEDSTATUSCODES\r\n'
reply: '250-XXXXXXXA\r\n'
reply: '250-AUTH\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-BINARYMIME\r\n'
reply: '250 XXXXXXXB\r\n'
reply: retcode (250); Msg: ************************
SIZE 29360128
PIPELINING
DSN
ENHANCEDSTATUSCODES
XXXXXXXA
AUTH
8BITMIME
BINARYMIME
XXXXXXXB
Traceback (most recent call last):
  File "C:\Users\Desktop\Send_6lisa.py", line 53, in send
    smtp.login(self.smtp_user, self.smtp_passwd)
  File "F:\Python25\lib\smtplib.py", line 587, in login
    if code == 334:
SMTPException: No suitable authentication method found.

参考网址:http://u.cxyblog.com/14/article-aid-304.html

按照网上说的方法对smtplib.py进行了修改,如下

       AUTH_PLAIN = "PLAIN"  
  1.         AUTH_CRAM_MD5 = "CRAM-MD5"  
  2.         AUTH_LOGIN = "LOGIN"  
  3.   
  4.         if self.helo_resp is None and self.ehlo_resp is None:   
  5.             if not (200 <= self.ehlo()[0] <= 299):   
  6.                 (code, resp) = self.helo()   
  7.                 if not (200 <= code <= 299):   
  8.                     raise SMTPHeloError(code, resp)   
  9.   
  10.         if not self.has_extn("auth"):   
  11.             raise SMTPException("SMTP AUTH extension not supported by server.")   
  12.   
  13.         # Authentication methods the server supports:   
  14.         authlist = self.esmtp_features["auth"].split()   
  15.   
  16.         # List of authentication methods we support: from preferred to   
  17.         # less preferred methods. Except for the purpose of testing the weaker   
  18.         # ones, we prefer stronger methods like CRAM-MD5:   
  19.         #preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN]   
  20.         preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN, AUTH_LOGIN]# add LOGIN    
  21.         #preferred_auths = [AUTH_PLAIN, AUTH_CRAM_MD5]   
  22.   
  23.         # Determine the authentication method we'll use   
  24.         authmethod = None  
  25.         for method in preferred_auths:   
  26.             if method in authlist:   
  27.                 authmethod = method   
  28.                 break  
  29. [color=red]            if '='+method in authlist:   
  30.                     authmethod = method   
  31.                     break # 本来这个部分不用加,但是我那个邮件服务器返回的是 auth=LOGIN,多了一个'=',所以我就加了这一段[/color]   
  32.         if self.debuglevel > 0:   
  33.             print "AuthMethod:", authmethod   
  34.         if authmethod == AUTH_CRAM_MD5:   
  35.             (code, resp) = self.docmd("AUTH", AUTH_CRAM_MD5)   
  36.             if code == 503:   
  37.                 # 503 == 'Error: already authenticated'   
  38.                 return (code, resp)   
  39.             (code, resp) = self.docmd(encode_cram_md5(resp, user, password))   
  40.         elif authmethod == AUTH_PLAIN:   
  41.             (code, resp) = self.docmd("AUTH",   
  42.                 AUTH_PLAIN + " " + encode_plain(user, password))   
  43.          
  44. # 主要就是下面这一段了             
  45. [color=red]       elif authmethod == AUTH_LOGIN:   
  46.             (code, resp) = self.docmd("AUTH", AUTH_LOGIN)   
  47.             if code == 334:   
  48.                 (code, resp) = self.docmd(base64.encodestring(user)[:-1])   
  49.                 if code == 334:   
  50.                     (code, resp) = self.docmd(base64.encodestring(password)[:-1])   [/color]       
  51.        elif authmethod == None:   
  52.             raise SMTPException("No suitable authentication method found.")   
  53.         if code not in [235503]:   
  54.             # 235 == 'Authentication successful'   
  55.             # 503 == 'Error: already authenticated'   
  56.             raise SMTPAuthenticationError(code, resp)   
  57.         return (code, resp)  
AUTH_PLAIN = "PLAIN"
        AUTH_CRAM_MD5 = "CRAM-MD5"
        AUTH_LOGIN = "LOGIN"

        if self.helo_resp is None and self.ehlo_resp is None:
            if not (200 <= self.ehlo()[0] <= 299):
                (code, resp) = self.helo()
                if not (200 <= code <= 299):
                    raise SMTPHeloError(code, resp)

        if not self.has_extn("auth"):
            raise SMTPException("SMTP AUTH extension not supported by server.")

        # Authentication methods the server supports:
        authlist = self.esmtp_features["auth"].split()

        # List of authentication methods we support: from preferred to
        # less preferred methods. Except for the purpose of testing the weaker
        # ones, we prefer stronger methods like CRAM-MD5:
        #preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN]
        preferred_auths = [AUTH_CRAM_MD5, AUTH_PLAIN, AUTH_LOGIN]# add LOGIN 
        #preferred_auths = [AUTH_PLAIN, AUTH_CRAM_MD5]

        # Determine the authentication method we'll use
        authmethod = None
        for method in preferred_auths:
            if method in authlist:
                authmethod = method
                break
[color=red]            if '='+method in authlist:
                    authmethod = method
                    break # 本来这个部分不用加,但是我那个邮件服务器返回的是 auth=LOGIN,多了一个'=',所以我就加了这一段[/color]
        if self.debuglevel > 0:
            print "AuthMethod:", authmethod
        if authmethod == AUTH_CRAM_MD5:
            (code, resp) = self.docmd("AUTH", AUTH_CRAM_MD5)
            if code == 503:
                # 503 == 'Error: already authenticated'
                return (code, resp)
            (code, resp) = self.docmd(encode_cram_md5(resp, user, password))
        elif authmethod == AUTH_PLAIN:
            (code, resp) = self.docmd("AUTH",
                AUTH_PLAIN + " " + encode_plain(user, password))
      
# 主要就是下面这一段了          
[color=red]       elif authmethod == AUTH_LOGIN:
            (code, resp) = self.docmd("AUTH", AUTH_LOGIN)
            if code == 334:
                (code, resp) = self.docmd(base64.encodestring(user)[:-1])
                if code == 334:
                    (code, resp) = self.docmd(base64.encodestring(password)[:-1])   [/color]    
       elif authmethod == None:
            raise SMTPException("No suitable authentication method found.")
        if code not in [235, 503]:
            # 235 == 'Authentication successful'
            # 503 == 'Error: already authenticated'
            raise SMTPAuthenticationError(code, resp)
        return (code, resp)



但是还是报的同样的错误。我同时也把发成功的debug打印的出来,发现是在AUTH的时候gmail,和126都会有一个AUTH_type=LOGIN
但是国外的邮件server却返回的是NONE

我就是不清楚这个auth_type在server端是怎么配置的,还有什么其他的方法可以发邮件的吗?谢谢!

 

参考网址:http://www.iteye.com/problems/50919

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值