| 
 | 
 | 
 <?php
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 namespace Service;
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 use Lib\Mail\MailFun;
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 /**
 | 
| 
 | 
 | 
  * @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', // 这个是新加坡服务器 代理
 | 
| 
 | 
 | 
         '43.154.117.107', // 这个是 shopk的那台服务器
 | 
| 
 | 
 | 
     ];
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
     /**
 | 
| 
 | 
 | 
      * 分配到的ip服务
 | 
| 
 | 
 | 
      * @var string
 | 
| 
 | 
 | 
      */
 | 
| 
 | 
 | 
     protected $assignIp = '';
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
     /**
 | 
| 
 | 
 | 
      * 邮箱
 | 
| 
 | 
 | 
      * @var string
 | 
| 
 | 
 | 
      */
 | 
| 
 | 
 | 
     protected $email = '';
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
     /**
 | 
| 
 | 
 | 
      * MailProxy constructor.
 | 
| 
 | 
 | 
      * @param string $email
 | 
| 
 | 
 | 
      * @param string $imap
 | 
| 
 | 
 | 
      * @param string $smtp
 | 
| 
 | 
 | 
      * @throws \Exception
 | 
| 
 | 
 | 
      */
 | 
| 
 | 
 | 
     public function __construct(string $email, string $imap, string $smtp)
 | 
| 
 | 
 | 
     {
 | 
| 
 | 
 | 
         $this->email = str_replace(['"',"'"],'',$email);
 | 
| 
 | 
 | 
         // 先分配
 | 
| 
 | 
 | 
         $this->assignEmail();
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         $this->originImapHost = $imap;
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         $this->originSmtpHost = $smtp;
 | 
| 
 | 
 | 
         // 解析
 | 
| 
 | 
 | 
         $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
 | 
| 
 | 
 | 
                 db()->throw()->update('mail_proxy',[
 | 
| 
 | 
 | 
                     'ip'    =>  $this->assignIp
 | 
| 
 | 
 | 
                 ],dbWhere(['email'=>$this->email]),false);
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         }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 ;
 | 
| 
 | 
 | 
         }
 | 
| 
 | 
 | 
         // 一个月活跃用户
 | 
| 
 | 
 | 
         $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){
 | 
| 
 | 
 | 
                     db()->throw()->update('mail_proxy',[
 | 
| 
 | 
 | 
                         'ip'    =>  $this->assignIp
 | 
| 
 | 
 | 
                     ],'id = '.$data['id']);
 | 
| 
 | 
 | 
                 }else{
 | 
| 
 | 
 | 
                     db()->throw()->insert('mail_proxy',[
 | 
| 
 | 
 | 
                         'email' =>  $this->email,
 | 
| 
 | 
 | 
                         'ip'    =>  $this->assignIp,
 | 
| 
 | 
 | 
                         'time'  =>  date('Y-m-d H:i:s'),
 | 
| 
 | 
 | 
                         'status'    =>  0
 | 
| 
 | 
 | 
                     ],false);
 | 
| 
 | 
 | 
                 }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
                 return ;
 | 
| 
 | 
 | 
             }
 | 
| 
 | 
 | 
         }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
         throw new \Exception('没有资源可分配');
 | 
| 
 | 
 | 
     }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
     /**
 | 
| 
 | 
 | 
      * 标记为正常使用代理
 | 
| 
 | 
 | 
      * @author:dc
 | 
| 
 | 
 | 
      * @time 2025/3/14 14:39
 | 
| 
 | 
 | 
      */
 | 
| 
 | 
 | 
     public function proxySuccess(){
 | 
| 
 | 
 | 
         db()->update('mail_proxy',[
 | 
| 
 | 
 | 
             'status'    =>  1
 | 
| 
 | 
 | 
         ],dbWhere(['email'=>$this->email]),false);
 | 
| 
 | 
 | 
     }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 }
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
 
 | 
| 
 | 
 | 
  | 
...
 | 
...
 | 
 |