2020年5月

邮件内容支持附件、图片、文字

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time     : 2020/5/13 6:05 下午
# @Author   : 陈日志
# @Email    : [email protected]
# @File     : Mail.py
import os
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.image import MIMEImage
from email.header import Header


class Mail(object):
    def __init__(self, smtp_server, smtp_port=25, ssl=False):
        self._message = MIMEMultipart()
        if ssl:
            self.smtp = smtplib.SMTP_SSL(smtp_server, 465 if smtp_port == 25 else smtp_port)
        else:
            self.smtp = smtplib.SMTP(smtp_server, smtp_port)
        self._receivers = None
        self._sender = None
        self._content = ''
        self._imageid = 0

    def login(self, user, password):
        try:
            self.smtp.login(user, password)
        except Exception as e:
            print(e)
            raise smtplib.SMTPAuthenticationError(1, "login failed")
        self._message["From"] = user
        self._sender = user

    @property
    def receives(self):
        return self._receivers

    @property
    def receives(self):
        return self._receivers

    @receives.setter
    def receives(self, receivers):
        type_ = type(receivers)
        if type_ is str:
            receivers = receivers.split(',')
            self._message["To"] = receivers
            self._receivers = receivers
        elif type_ is list or type_ is tuple:
            self._message["To"] = ','.join(receivers)
            self._receivers = receivers

    @property
    def title(self):
        return self._message.get("Subject")

    @title.setter
    def title(self, title):
        self._message["Subject"] = Header(title, 'utf-8')

    @property
    def content(self):
        return self._message

    @content.setter
    def content(self, content):
        self._content = content

    @property
    def imageid(self):
        self._imageid += 1
        return self._imageid

    def append_content(self, content):
        self._content += content

    def add_attachment(self, file):
        att = MIMEText(open(file, 'rb').read(), 'base64', 'utf-8')
        att["Content-Type"] = 'application/octet-stream'
        # att["Content-Disposition"] = 'attachment; filename=%s' % os.path.basename(file).encode('utf-8')
        att.add_header('Content-Disposition', 'attachment', filename=('utf-8', '', os.path.basename(file)))
        self._message.attach(att)

    def add_image(self, img):
        imageid = 'image%s' % self.imageid
        msg = MIMEImage(open(img, 'rb').read())
        msg.add_header('Content-ID', imageid)
        self._content += '<br/><img src="cid:%s">' % imageid
        self._message.attach(msg)

    def send(self):
        self._message.attach(MIMEText(self._content, 'html', 'utf-8'))
        try:
            self.smtp.sendmail(self._sender, self._receivers, self._message.as_string())
        except Exception as e:
            print(e)
            raise smtplib.SMTPConnectError(1, "Send mail error")

    def logout(self):
        self.smtp.quit()

- 阅读剩余部分 -

使用 Haproxy、Nginx 等软件反向代理 HTTP 协议时,往往会设置 X-Forwarded-For 等头部让后端 Web server 能正确取到客户端真实 IP。如果做 4 层代理,那么就得借助 Linux 的特性 TProxy 来实现,本文讲解如何配置 Haproxy、Nginx 来实现透明代理。

Haproxy

网上很多文章都说到 Haproxy 要重新编译,编译参数加上USE_LINUX_TPROXY=1。其实这种说法已经过时了,以 RHEL 系 Linux 发行版为例,RHEL6、RHEL7、RHEL8 官方提供的 rpm 包默认就加上了这个编译参数,因此如对版本无特殊要求,使用官方提供的版本就可以了,使用 yum install haproxy 安装即可。

使用限制

  • 代理服务器与后端服务器IP地址必须在同一个网段
  • 后端服务器的默认网关要指向代理服务器的地址*

代理服务器配置

haproxy

listen 80
    bind :80
    mode tcp
    source 0.0.0.0 usesrc clientip
    server server1 server1:8080 weight 1

关键配置 source 0.0.0.0 usesrc clientip

- 阅读剩余部分 -