天天看點

python通過163郵箱發送email郵件發送郵件代碼封裝成簡單郵件發送子產品執行個體:整點報時發郵件scrapy中發送郵件優化後的簡單實用

發送郵件代碼

# !/usr/bin/python
    # -*- coding: UTF-8 -*-

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

    # 第三方 SMTP 服務
    mail_host = "smtp.163.com"  # 設定伺服器
    mail_user = "[email protected]"  # 使用者名
    mail_pass = "xxx"  # 密碼

    sender = mail_user
    sender_name = "admin"  # 顯示名稱
    receiver = '[email protected]'  
    # 接收郵件,可設定為你的QQ郵箱或者其他郵箱,清單 發送會報錯

    # 郵件内容
    message = MIMEText("正文内容", 'plain', 'utf-8')
    message['From'] = "{0}<{1}>".format(sender_name ,sender)
    message['To'] = receiver
    message['Subject'] = Header("标題", 'utf-8')

    try:
        smtpObj = smtplib.SMTP()
        smtpObj.connect(mail_host, 25)  # 25 為 SMTP 端口号
        smtpObj.login(mail_user, mail_pass)
        smtpObj.sendmail(sender, receiver, message.as_string())
        print "郵件發送成功"
        smtpObj.quit()
        smtpObj.close()
    except smtplib.SMTPException as e:
        print "Error: 無法發送郵件", e      

封裝成簡單郵件發送子產品

# email_helper.py

from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
import smtplib

debug = True  # debug開關


def debug_info(text):
    if debug == True:
        print(text)


class EmailClient(object):
    '郵件發送端初始化類'

    def __init__(self, smtp_server):
        '初始化伺服器位址'
        self._smtp_server = smtp_server
        self.addrs = []  # 郵件位址清單, 格式(addr, name)

    def login(self, from_addr, password, from_name=None):
        '登入'
        self._from_addr = from_addr
        self._password = password
        if from_name == None:
            self._from_name = from_addr
        else:
            self._from_name = from_name

        try:
            self.server = smtplib.SMTP(self._smtp_server, 25)
            # server.set_debuglevel(1)
            self.server.login(self._from_addr, self._password)
        except Exception as e:
            return -1  # 登入失敗
            debug_info("登入失敗")
        else:
            return 0  # 登入成功
            debug_info("登入成功")

    def _send(self, title, text, to_addr, to_name=None):
        '發送郵件'
        if to_name == None: to_name = to_addr

        try:
            # 接受方資訊
            msg = MIMEText(text, 'plain', 'utf-8')
            msg['From'] = self._format_addr('%s<%s>' % (
                          self._from_name, self._from_addr))

            msg['To'] = self._format_addr('%s <%s>' % (to_name, to_addr))
            msg['Subject'] = Header(title, 'utf-8').encode()

            # 發送内容
            self.server.sendmail(self._from_addr, to_addr, msg.as_string())

            return 0

        except Exception as e:
            debug_info(e)
            return -1

    def add_address(self, addr, name=None):
        '增加位址到位址清單'
        if name == None: name = addr
        self.addrs.append((addr, name))

    def send_all(self, title, text):
        '發送所有人'
        success = 0
        fail = 0
        for addr, name in self.addrs:
            ret = self._send(title, text, addr, name)
            if ret == 0:
                success += 1
            else:
                fail += 1
        return success, fail

    def __del__(self):
        '析構'
        self.server.quit()

    def _format_addr(self, s):
        '格式化位址'
        name, addr = parseaddr(s)
        return formataddr((Header(name, 'utf-8').encode(), addr))


if __name__ == '__main__':
    # 郵箱伺服器位址
    email_client = EmailClient("smtp.163.com")

    # 登陸,密碼或授權碼
    email_client.login("[email protected]", "password")

    # 增加收件人
    email_client.add_address("[email protected]")
    email_client.add_address("email")
    email_client.add_address("email")

    # 發送
    title = "郵件标題"
    body = "郵件内容,試試看能不能發送出去"
    success, fail = email_client.send_all(title, body)

    # 傳回發送結果
    print("success:", success, "fail:", fail)      

執行個體:整點報時發郵件

引入上面的子產品檔案,當整點的時候就給自己的郵件發一份郵件,彙報現在時刻

# email_demo.py

from email_helper import EmailClient
from datetime import datetime
import time

email_client = EmailClient("smtp.163.com")  # 郵箱伺服器位址

email_client.login("[email protected]", "xxx")  # 登陸

email_client.add_address("[email protected]")  # 增加收件人

#  發送
while True:
    now = datetime.now()
    if now.minute == 0 and now.second == 0:
        title = "整點時間提醒郵件"
        body = "現在時刻:%s"%now
        success, fail = email_client.send_all(title, body)
        
        print("success:", success, "fail:", fail)  # 傳回發送結果
        time.sleep(5)      

scrapy中發送郵件

如果是使用scrapy 爬蟲架構,就比較簡單了,直接使用如下代碼就行,當然也可以将參數配置到setting檔案裡,多次調用參數。

ps:單獨測試沒有成功,運作爬蟲項目中測試才行      
# -*- coding:utf-8 -*-

# 測試郵箱發送
from scrapy.mail import MailSender

mailer = MailSender(smtphost='smtp.163.com',
                    mailfrom="[email protected]",
                    smtpuser="[email protected]",
                    smtppass="xxxxx",
                    smtpport=25)

mailer.send(to=["[email protected]"],
            subject="請查收",
            body="hello world")      

優化後的簡單實用

支援25端口和465端口設定

# -*- coding: utf-8 -*-

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


class EmailSender(object):
    # 郵箱配置
    # 伺服器位址
    MAIL_HOST = "smtp.163.com"
    # 伺服器端口 25 或者 465(ssl)
    MAIL_PORT = 465

    # 發件人郵箱賬号
    MAIL_USER = "[email protected]"
    # 發件人郵箱密碼
    MAIL_PASS = "123456"
    # 發件人郵箱别名
    MAIL_NAME = "xxx"

    # 收件人位址
    MAIL_TO = "[email protected]"

    @classmethod
    def send(cls, subject, text, to_addrs=None):
        msg = cls._get_email(subject, text)

        # 發送郵件
        if cls.MAIL_PORT == 465:
            server = smtplib.SMTP_SSL(cls.MAIL_HOST)  # ssl 465端口
        else:
            server = smtplib.SMTP(cls.MAIL_HOST, cls.MAIL_PORT)  # 25端口

        # 發送位址
        if to_addrs is None:
            to_addrs = [cls.MAIL_TO]

        server.login(cls.MAIL_USER, cls.MAIL_PASS)  # 登入
        server.sendmail(cls.MAIL_USER, to_addrs, msg.as_string())  # 發送
        server.quit()  # 退出

    @classmethod
    def _get_email(cls, subject, text):

        # 構造郵件
        msg = MIMEText(text, 'plain', 'utf-8')
        # 郵箱昵稱、發件人郵箱賬号
        msg['From'] = formataddr([cls.MAIL_NAME, cls.MAIL_USER])
        msg['To'] = formataddr([cls.MAIL_TO, cls.MAIL_TO])
        msg['Subject'] = subject
        return msg


if __name__ == '__main__':
    EmailSender.send("你好", "這是内容")
         

參考:

  1. SMTP發送郵件 - 廖雪峰部落格
  2. Python SMTP發送郵件 - 菜鳥教程
  3. scrapy 發送email