python smtplib 使用代理发送邮件

背景:部署代码主机安装了hadoop client,为保证数据安全,禁止了主机外网,但是上面的监控程序需要发送外网告警邮件。

技术方案:使用3proxy软件在跳板机开通代理端口,smtplib使用代理发送邮件。

涉及软件:3proxy,socks介绍

socks安装

# 主机没有外网只能通过代理安装,代理IP使用时请自行更换
sudo pip --proxy=192.168.*.*:6667 install PySocks

代码改造

# 注意使用的端口为socks端口
if proxy:
    socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '192.168.*.*', 6666)
    socks.wrapmodule(smtplib)

测试示例(可以结合下面分享的Mail类分析)

# 不使用代理调用代码
mail = Mail(mail_host, mail_user, mail_pass)
mail(mailto_list, subject % (calc_date(date_id, offset), date_id), body, None)
# 执行结果
$ python hdfs_report.py 20170715
[INFO ] [2017-07-15 10:58:36] 初始化Jinjia2模板....
[INFO ] [2017-07-15 10:58:36] 初始化邮箱....
[ERROR] [2017-07-15 10:58:36] [Mail->__init__] --> errmsg:[Errno 101] Network is unreachable
[INFO ] [2017-07-15 10:58:36] 开始发送邮件....
[ERROR] [2017-07-15 10:58:36] [send_mail] --> errmsg:please run connect() first
Exception AttributeError: "SMTP instance has no attribute 'sock'" in <bound method Mail.__del__ of <util.Mail instance at 0xff7ab8>> ignored

# 使用代理调用代码,初始化mail类时添加 proxy=True 参数
mail = Mail(mail_host, mail_user, mail_pass, proxy=True)
mail(mailto_list, subject % (calc_date(date_id, offset), date_id), body, None)
# 执行结果
$ python hdfs_report.py 20170715
[INFO ] [2017-07-15 11:01:31] 初始化Jinjia2模板....
[INFO ] [2017-07-15 11:01:31] 初始化邮箱....
[INFO ] [2017-07-15 11:01:31] 使用代理发送....
[INFO ] [2017-07-15 11:01:31] 开始发送邮件....
[INFO ] [2017-07-15 11:01:31] 邮件发送成功....

分享自己的Mail类

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2017/4/26 15:35
# @Author  : Dengsc
# @Site    : 
# @File    : util.py
# @Software: PyCharm


import os
import time
import socks
import datetime
import smtplib
from email.mime.text import MIMEText
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from jinja2 import Environment, FileSystemLoader
from string import Template


class Logs:
    """
    日志格式化数据工具类
    """

    def __init__(self):
        self.fmt = '%Y-%m-%d %H:%M:%S'

    def __call__(self,  log_type, msg):
        """
            日志格式化输出
            :param log_type: INFO ERROR WARN
            :param msg: MSG TEXT
            :return: None
        """

        date_detail = time.strftime(self.fmt)
        log_text = '[%s] %s' % (date_detail, msg)
        if log_type == 'INFO':
            print '\033[32;1m[INFO ] %s\033[0m' % log_text
        elif log_type == 'ERROR':
            print '\033[31;1m[ERROR] %s\033[0m' % log_text
        elif log_type == 'WARN':
            print '\033[33;1m[WARN ] %s\033[0m' % log_text


class Mail:
    """
    邮件发送工具类
    """
    def __init__(self, mail_host, mail_user, mail_pass, proxy=False):
        """
        初始化邮箱设置
        :param mail_host: string 邮箱服务器地址 
        :param mail_user: string 发件人
        :param mail_pass: string 密码
        :param proxy: boolean
        """
        try:
            log('INFO', '初始化邮箱....')
            if proxy:
                log('INFO', '使用代理发送....')
                socks.setdefaultproxy(socks.PROXY_TYPE_SOCKS5, '192.168.*.*', 6666)
                socks.wrapmodule(smtplib)
            self.me = '<' + mail_user + '>'
            self.server = smtplib.SMTP()
            self.server.connect(mail_host)
            self.server.login(mail_user, mail_pass)
        except Exception as e:
            log('ERROR', '[Mail->__init__] --> errmsg:%s' % (str(e)))

    def __call__(self, to_list, sub, body, images):
        """
        邮件发送
        :param to_list: list 收件人列表 
        :param sub:  string 主题
        :param body:  string 正文
        :param images:  dict 图片
        :return:  None
        """
        def add_img(src, img_id):
            """
            邮件正文添加图片
            :param src: string 图片路径
            :param img_id: string 图片id
            :return: MIMEImage
            """
            try:
                fp = open(src, 'rb')
                msg_image = MIMEImage(fp.read())
                fp.close()
                msg_image.add_header('Content-ID', img_id)
                return msg_image
            except Exception as ex:
                log('ERROR', '[Mail->__call__->add_img] --> errmsg:%s' % (str(ex)))

        msg = MIMEMultipart('related')
        msg_text = MIMEText(body, 'html', 'utf-8')
        msg.attach(msg_text)
        if images:
            for k, v in images.iteritems():
                msg.attach(add_img(k, v))

        msg['Subject'] = sub
        msg['From'] = self.me
        msg['To'] = ','.join(to_list)
        try:
            log('INFO', '开始发送邮件....')
            self.server.sendmail(self.me, to_list, msg.as_string())
            log('INFO', '邮件发送成功....')
        except Exception, e:
            log('ERROR', '[send_mail] --> errmsg:%s' % (str(e)))

    def __del__(self):
        self.server.close()

log = Logs()

好了,目前邮件又可以正常发送了,关于socks的更多使用方法请移步官网哦。

转载于:https://my.oschina.net/cdsc/blog/1408147

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值