python smtplib 使用代理发送邮件

本文介绍了在服务器禁止外网连接的情况下,如何通过配置代理服务器并利用socks5协议实现发送外网邮件的方法。文中详细展示了使用3proxy作为代理软件,并通过修改Python smtplib模块以支持代理发送邮件的具体步骤。
Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

背景:部署代码主机安装了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

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值