MailProxy.php 7.2 KB
<?php

namespace Service;

use Lib\Mail\MailFun;
use Model\emailSql;
use Model\listsSql;

/**
 * @author:dc
 * @time 2025/3/11 9:20
 * Class MailProxy
 * @package Service
 */
class MailProxy {

    /** 原域名
     * @var
     */
    protected $originImapHost = '';

    protected $originSmtpHost = '';


    /**
     * 代理服务器
     * @var string
     */
    private $proxyImapHost = '';

    private $proxySmtpHost = '';

    /**
     * 代理配置
     * @var array
     */
    protected $config = [

        'smtp.gmail.com:465' =>  '10087',
        'imap.gmail.com:993' =>  '10086',

        'imap-mail.outlook.com:993' =>  '10088',
        'smtp-mail.outlook.com:465' =>  '10089',

        'imap.mail.yahoo.com:993' =>  '10092',
        'smtp.mail.yahoo.com:465' =>  '10093',

        'imaphz.qiye.163.com:993' =>  '10080',
        'smtphz.qiye.163.com:465' =>  '10081',

        'imap.qiye.aliyun.com:993' =>  '10094',
        'smtp.qiye.aliyun.com:465' =>  '10095',

//        'imap.qq.com:993' =>  '10096',
//        'smtp.qq.com:465' =>  '10097',

    ];

    /**
     * 代理服务器 地址
     * @var string[]
     */
    protected $proxyService = [
        '43.134.162.250', // 这个是新加坡服务器 代理
        '119.28.113.113', // 这个是新加坡服务器 代理02
//        '43.154.117.107', // 这个是 shopk的那台服务器
    ];

    /**
     * 分配到的ip服务
     * @var string
     */
    protected $assignIp = '';

    /**
     * 邮箱
     * @var string
     */
    protected $email = '';

    protected $defaultIp = '';

    /**
     * MailProxy constructor.
     * @param string $email
     * @param string $imap
     * @param string $smtp
     * @param string $default
     * @throws \Exception
     */
    public function __construct(string $email, string $imap, string $smtp,string $default='')
    {
        $this->email = str_replace(['"',"'"],'',$email);

        if($default){
            $this->defaultIp = $default;
        }

        // 先分配
        $this->assignEmail();

        $this->originImapHost = $imap;

        $this->originSmtpHost = $smtp;
        // 不需要分配
        if($this->assignIp===false){
            // 解析
            $this->proxyImapHost = $imap;
            // 解析
            $this->proxySmtpHost = $smtp;
        }else{
            // 解析
            $this->proxyImapHost = $this->parse($imap,993);
            // 解析
            $this->proxySmtpHost = $this->parse($smtp,465);
        }


    }

    /**
     * 代理地址
     * @author:dc
     * @time 2025/3/13 17:38
     */
    public function getImapProxy(){
        return $this->proxyImapHost;
    }

    /**
     * 代理地址
     * @return string
     * @author:dc
     * @time 2025/3/14 10:31
     */
    public function getSmtpProxy(){
        return $this->proxySmtpHost;
    }

    /**
     * @return mixed
     */
    public function getOriginImapHost(): string
    {
        return $this->originImapHost;
    }

    /**
     * @return string
     */
    public function getOriginSmtpHost(): string
    {
        return $this->originSmtpHost;
    }

    /**
     * 解析地址
     * @param string $host
     * @param int $port
     * @return string
     * @author:dc
     * @time 2025/3/13 17:18
     */
    public function parse(string $host, int $port){
        $host = parse_url($host);
        // 协议
        $scheme = $host['scheme']??'ssl';
        // 地址
        $serve = strtolower(empty($host['host']) ? $host['path'] : $host['host']);

        // 传入的是代理地址 并且是数据库里面已分配的ip
        if(in_array($serve,$this->proxyService)){
            // 传入的服务器 和 分配的不一致 更新分配的
            if($serve != $this->assignIp){
                $this->assignIp = $serve;
                // 更新 ip
                $this->updateIp();
            }

        }else{
            // 端口
            $port = (empty($host['port'])?$port:$host['port']);

            // 端口不在,说明没有配置
            if(empty($this->config[$serve.':'.$port])){
                // 返回不代理
                $this->assignIp = $serve;
            }else{
                if(in_array($this->assignIp,$this->proxyService)){
                    $port = $this->config[$serve.':'.$port]; // 代理服务器端口
                }
            }

        }

        // 组装
        $proxyHost = $scheme.'://'.$this->assignIp.":".(empty($host['port'])?$port:$host['port']);


        return implode(':',MailFun::getHostPort($proxyHost));
    }

    /**
     * 分配邮箱 到 服务器
     * @author:dc
     * @time 2025/3/11 18:01
     */
    private function assignEmail(){
        $data = db()->throw()->first('select * from mail_proxy where email = "'.$this->email.'"');
        // 存在记录 并且 还在服务器列表
        if($data && in_array($data['ip'],$this->proxyService)){
            $this->assignIp = $data['ip'];
            return ;
        }

        if(!$data){
            // 如果 已经有之前的邮箱了, 就不进行代理了
            if(db()->count(emailSql::first($this->email))){
                $this->assignIp = false;
                return ;
            }
        }

        // 默认指定 ip
        if($this->defaultIp){
            $this->assignIp = $this->defaultIp;
            if($data){
                if($data['ip'] == $this->defaultIp){
                    return ;
                }else{
                    $this->updateIp();
                }
            }else{
                $this->createIp();
            }
            return ;
        }

        // 一个月活跃用户
        $t = date('Y-m-d H:i:s',strtotime("-30 day"));
        foreach ($this->proxyService as $ip){
            $num = db()->count("select count(*) from `mail_proxy` where `status` = 1 and `time` > '{$t}' and `ip` = '{$ip}'");
            // 每个ip分配1000个
            if($num<1000){
                $this->assignIp = $ip;
                // 如果某个服务器 停止了,进来了就要重新分配
                if($data){
                    $this->updateIp();
                }else{
                    $this->createIp();
                }

                return ;
            }
        }

        throw new \Exception('没有资源可分配');
    }

    /**
     * 更新ip
     * @param $ip
     * @author:dc
     * @time 2025/3/14 15:55
     */
    protected function updateIp(){
        db()->throw()->update('mail_proxy',[
            'ip'    =>  $this->assignIp,
            'time'  =>  date('Y-m-d H:i:s'),
        ],dbWhere(['email'=>$this->email]),false);
    }

    /**
     * 创建
     * @author:dc
     * @time 2025/3/14 15:57
     */
    protected function createIp(){
        db()->throw()->insert('mail_proxy',[
            'email' =>  $this->email,
            'ip'    =>  $this->assignIp,
            'time'  =>  date('Y-m-d H:i:s'),
            'status'    =>  0
        ],false);
    }

    /**
     * 标记为正常使用代理
     * @author:dc
     * @time 2025/3/14 14:39
     */
    public function proxySuccess(){
        db()->update('mail_proxy',[
            'status'    =>  1,
            'time'  =>  date('Y-m-d H:i:s'),
        ],dbWhere(['email'=>$this->email]),false);
    }



}