背景:部署代码主机安装了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的更多使用方法请移步官网哦。