作者 邓超

proxy

<?php
namespace Controller;
use Lib\Mail\Mail;
use Lib\Mail\MailFun;
use Lib\UploadFile;
use Lib\Verify;
use Model\bodySql;
use Model\emailSql;
use Model\folderSql;
use Model\listsSql;
use Model\sendJobsSql;
use Service\MailProxy;
use Service\SyncMail;
/**
* 读取代理服务器配置
* @author:dc
* @time 2025/3/10 16:36
* Class ServerProxy
* @package Controller
*/
class ServerProxy extends Base {
/**
* shopk和mail-server都必须使用这个 进行分配
* @return array[]
* @author:dc
* @time 2025/3/10 16:39
*/
public function index(){
$email = app()->request('email');
$smtp = app()->request('smtp');
$imap = app()->request('imap');
$proxy = new MailProxy($email,$imap,$smtp);
$proxy->proxySuccess();
app()->_json([
'imap_proxy' => $proxy->getImapProxy(),
'smtp_proxy' => $proxy->getSmtpProxy()
]);
}
}
... ...
server {
listen 10087; # 监听的端口
proxy_pass smtp.gmail.com:465;
}
server {
listen 10086; # 监听的端口
proxy_pass imap.gmail.com:993;
}
server {
listen 10088; # 监听的端口
proxy_pass imap-mail.outlook.com:993;
}
server {
listen 10089; # 监听的端口
proxy_pass smtp-mail.outlook.com:465;
}
server {
listen 10092; # 监听的端口
proxy_pass imap.mail.yahoo.com:993;
}
server {
listen 10093; # 监听的端口
proxy_pass smtp.mail.yahoo.com:465;
}
server {
listen 10080; # 监听的端口
proxy_pass imaphz.qiye.163.com:993;
}
server {
listen 10081; # 监听的端口
proxy_pass smtphz.qiye.163.com:465;
}
server {
listen 10094; # 监听的端口
proxy_pass imap.qiye.aliyun.com:993;
}
server {
listen 10095; # 监听的端口
proxy_pass smtp.qiye.aliyun.com:465;
}
... ...
... ... @@ -7,18 +7,19 @@
return [
'/' => [\Controller\Test::class, 'home'],
'axxx' => [\Controller\Test::class, 'a'],
// 登录操作
'login' => [\Controller\Login::class, 'login'],
// 邮件列表
'lists' => [\Controller\Home::class, 'lists'],
'lists' => [\Controller\HomeEs::class, 'lists'],
// 统计
'count' => [\Controller\Home::class, 'count'],
'count' => [\Controller\HomeEs::class, 'count'],
// 这个是单独处理的 aicc那边的应用
'v2/lists' => [\Controller\v2\Home::class, 'lists'],
// 黑格专用路由
'fob/lists' => [\Controller\fob_ai\MailListV2::class, 'lists'],
'fob/count' => [\Controller\fob_ai\MailListV2::class, 'count'],// 统计数量
'fob/lists' => [\Controller\fob_ai\MailListV2Es::class, 'lists'],
'fob/count' => [\Controller\fob_ai\MailListV2Es::class, 'count'],// 统计数量
'fob/v2/lists' => [\Controller\fob_ai\MailListV2::class, 'lists'],
'fob/v2/count' => [\Controller\fob_ai\MailListV2::class, 'count'],// 统计数量
... ... @@ -27,6 +28,9 @@ return [
'fob/es/count' => [\Controller\fob_ai\MailListV2Es::class, 'count'],// 统计数量
// 代理 ip分配
'proxy/server' => [\Controller\ServerProxy::class,'index'],
// 邮件详情
... ...
<?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);
}
}
... ...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<style>
pre{
background-color: #f0f0f0;
}
</style>
<h3><div style="text-align:center">深圳国际贸易单一窗口业务对接创贸集团技术方案</div></h3>
<p>> 一. 签名</p>
<ol>
<li>签名采用rsa 2048</li>
</ol>
<pre>
<code class="language-injectablephp">
/**
* rsa 签名
* @param array $data 请求的参数
* @return string 签名字符串
*/
function rsaEnSign(array $data){
ksort($data);
$dataString = http_build_query($data);
if (openssl_sign($dataString, $signature, 'private_key', OPENSSL_ALGO_SHA1)) {
return base64_encode($signature);
} else {
return '';
}
}
</code>
</pre>
<ol start="2">
<li>验证数据</li>
</ol>
<pre>
<code class="language-injectablephp">
/**
* 验证数据来源
* @param array $data
* @param string $sign
*/
function rsaVerify(array $data, string $sign){
ksort($data);
$dataString = http_build_query($data);
$verified = openssl_verify($dataString, base64_decode($sign), 'public_key', OPENSSL_ALGO_SHA1);
if ($verified === 1) {
// 验证成功
} elseif ($verified === 0) {
// 验证失败
} else {
// 签名错误
$errorMsg = openssl_error_string();
}
}
</code>
</pre>
<p>> 二. 接口</p>
<ol>
<li><p>用户授权</p>
<ul>
<li>请求地址 /api/southern/auth</li>
<li>请求类型 POST</li>
<li>签名规则 rsa</li>
<li>请求示例</li>
</ul>
<pre>
<code class="language-injectablephp">
$postData = [
'payload' => [
"serviceFlowId" => "本次业务操作流水id",
"uniCode" => "南方电子口岸给对接方分配的 唯一ID号",
"mobile" => "手机",
"userId" => "用户 ID",
"userName" => "用户名称",
"entName" => "企业名称",
"scCode" => "企业统一社会信用代码"
],
'sign' => '',
];
$postData['sign'] = rsaEnSign($postData['payload']);
$result = Http::post('url', $postData);
if($result['code']===200){
// 成功
}else{
// 失败
}
</code>
</pre>
<ul>
<li>返回结果 成功</li>
</ul>
<pre>
<code class="language-json">
{
"code": 200,
"message": "SUCCESS",
"data": {
"url": [
{
"name": "ai搜索",
"url": "https://fob.ai.cc/ai_search?iframe_sign=xxxxx"
},
{
"name": "企业洞察",
"url": "https://fob.ai.cc/ai_company_search?iframe_sign=xxxxx"
},
...
],
"uniCode": "1",
"firstLogin": true //是否第一次登录
},
"success": true
}
</code></pre>
<ul>
<li>失败信息</li>
</ul>
<pre>
<code class="language-json">
{
"code": 500,
"message": "签名验证失败",
"success": false
}
</code>
</pre>
</li>
<li><p>意向登记</p>
<ul>
<li>请求地址 /api/southern/intention</li>
<li>请求类型 POST</li>
<li>签名规则 rsa</li>
<li>请求示例</li>
</ul>
<pre><code class="language-injectablephp">
$postData = [
"guid"=>"166970C4-AF54-470A-87E4-D598463783A2",
"busiCode"=> "CMJT04",
"senderId"=> "XXXXXX",
"version"=> "1.0",
'payload' => [
"serviceFlowId"=> "F2310011420000001",
"orgName"=>"xxx",
"orgCode"=>"xxx",
"userId"=>"xxx",
"userName"=>"xxxxx 有限公司",
"contactAddress"=> "xxxxxxxxxxxxxxxxxx",
"contactMan"=> "xxx",
"contactTel"=> "xxx",
"email"=> "xxx",
"position"=> "xxx",
"notes"=> "xxx"
],
'sign' => '',
];
$postData['sign'] = rsaEnSign($postData['payload']);
$result = Http::post('url', $postData);
if($result['code']===200){
// 成功
}else{
// 失败
}
</code></pre>
<ul>
<li>返回结果 成功</li>
</ul>
<pre>
<code class="language-json">
{
"code": 200,
"message": "SUCCESS",
"data": {
"serviceFlowId": "F2310011420000001",
"status": "11",
"statusTime": "20230818081331",
"statusDetail": ""
},
"success": true
}
</code>
</pre>
<ul>
<li>失败信息</li>
</ul>
<pre><code class="language-json">
{
"code": 500,
"message": "签名验证失败",
"success": false
}</code></pre>
</li>
</ol>
</body>
</html>
\ No newline at end of file
... ...