收件箱读取(初始版本)
This commit is contained in:
4
.env
4
.env
@@ -6,6 +6,10 @@ send_email_password = Wu999999tmrwe
|
||||
;审核建议邮箱
|
||||
editor_email = publisher@tmrjournals.com
|
||||
|
||||
;读取的企业邮箱
|
||||
mail_server = imap.qq.com
|
||||
|
||||
|
||||
[journal]
|
||||
;官网服务器地址
|
||||
base_url = http://journalapi.tmrjournals.com/public/index.php
|
||||
202
application/api/controller/Inbox.php
Normal file
202
application/api/controller/Inbox.php
Normal file
@@ -0,0 +1,202 @@
|
||||
<?php
|
||||
|
||||
namespace app\api\controller;
|
||||
use email\receiveMails;
|
||||
use think\Controller;
|
||||
use think\Db;
|
||||
use think\Env;
|
||||
use think\Validate;
|
||||
|
||||
class Inbox extends Controller{
|
||||
|
||||
protected $inbox_obj = '';
|
||||
protected $inbox_attachment_obj = '';
|
||||
protected $journal_obj = '';
|
||||
|
||||
public function __construct(\think\Request $request = null) {
|
||||
|
||||
parent::__construct($request);
|
||||
$this->inbox_obj = Db::name('inbox');
|
||||
$this->inbox_attachment_obj = Db::name('inbox_attachment');
|
||||
$this->journal_obj = Db::name('journal');
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收件箱邮件
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
public function getInbox(){
|
||||
|
||||
$server = new receiveMails();
|
||||
$journals=[
|
||||
[ 'journal_id'=>2,
|
||||
'email'=>'1586428462@qq.com',
|
||||
'epassword'=>'rthlprelzzfphigh'
|
||||
]
|
||||
];
|
||||
foreach ($journals as $journal){
|
||||
|
||||
//1. 连接邮箱 传入参数
|
||||
$server->connect($journal);
|
||||
|
||||
//2. 获取邮件数
|
||||
$emailNums = $server->getTotalMails();
|
||||
|
||||
if($emailNums){
|
||||
|
||||
$insertData=[];
|
||||
|
||||
foreach ($emailNums as $key=>$value){
|
||||
|
||||
//2.1 获取邮件头部信息
|
||||
$head = $server->getHeaders($value);
|
||||
|
||||
//2.2 处理邮件附件
|
||||
$files = $server->getAttach($value);
|
||||
// 附件
|
||||
$head['url'] =[];
|
||||
|
||||
//2.3 处理正文中的图片
|
||||
$imageList=array();
|
||||
$section = 2;
|
||||
if($files){
|
||||
foreach($files as $k => $file)
|
||||
{
|
||||
|
||||
//type=1为附件,0为邮件内容图片
|
||||
if($file['type'] == 0)
|
||||
{
|
||||
$imageList[$k]=$file['pathname'];
|
||||
}
|
||||
|
||||
if($file['type'] == 1)
|
||||
{
|
||||
array_push($head['url'],$file['url']);
|
||||
}
|
||||
|
||||
if(($file['type'] == 0 || $file['type'] == 1) && !empty($file['url'])){
|
||||
|
||||
$section = 1.2 ;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$webPath = ROOT_PATH.'public' . DS . 'contentImg' . DS . date('Ymd') .DS ;
|
||||
// 正文内容
|
||||
$head['content'] = $server->getBody($value,$webPath,$imageList,$section);
|
||||
array_push($insertData,$head);
|
||||
}
|
||||
$this->insertData($insertData,$journal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 后台展示 收件箱
|
||||
public function getInboxList(){
|
||||
|
||||
$data = $this->request->post();
|
||||
// 验证规则
|
||||
$rule = new Validate([
|
||||
'pageIndex'=>'require|number',
|
||||
'pageSize'=>'require|number'
|
||||
]);
|
||||
if(!$rule->check($data)){
|
||||
return json(['code' => 1,'msg'=>$rule->getError()]);
|
||||
}
|
||||
|
||||
$res['data'] = $this->inbox_obj->field('t_inbox.*,t_inbox_attachment.attachmentUrl')
|
||||
->join('t_inbox_attachment','t_inbox_attachment.emailId = t_inbox.id','LEFT')
|
||||
->page($data['pageIndex'],$data['pageSize'])
|
||||
->select();
|
||||
|
||||
$res['data']= $this->inbox_obj->field('id,sendEmail,title,content,creatTime,isaAtachment')->page($data['pageIndex'],$data['pageSize'])->select();
|
||||
|
||||
foreach ($res['data'] as $key=>$value ){
|
||||
$res['data'][$key]['attachmentUrl'] = $this->inbox_attachment_obj->where('emailId',$value['id'])->column('attachmentUrl');
|
||||
}
|
||||
|
||||
$res['total'] = $this->inbox_obj->count();
|
||||
|
||||
return jsonSuccess($res);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 已经存在邮件去除
|
||||
* @param $datas
|
||||
* @return mixed
|
||||
* @throws \think\db\exception\DataNotFoundException
|
||||
* @throws \think\db\exception\ModelNotFoundException
|
||||
* @throws \think\exception\DbException
|
||||
*/
|
||||
private function removeData($datas,$journal){
|
||||
|
||||
foreach ($datas as $key => $value){
|
||||
$res = $this->inbox_obj->where(['journalId'=>$journal['journal_id'],'eid'=>$value['emailId']])->find();
|
||||
if($res){
|
||||
unset($datas[$key]);
|
||||
}
|
||||
}
|
||||
return $datas;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入数据库
|
||||
* @param $datas
|
||||
*/
|
||||
private function insertData($datas,$journal){
|
||||
|
||||
$datas = $this->removeData($datas,$journal);
|
||||
|
||||
Db::startTrans();
|
||||
|
||||
try{
|
||||
foreach ($datas as $key=>$value){
|
||||
|
||||
$insert = [
|
||||
'journalId'=>$journal['journal_id'],
|
||||
'eid'=>$value['emailId'],
|
||||
'sendEmail'=>$value['from'],
|
||||
'title'=>$value['subject'],
|
||||
'content'=>$value['content'],
|
||||
'sendTime'=>$value['sendTime'],
|
||||
'creatTime'=>time(),
|
||||
'isaAtachment'=>empty($value['url'])?0:1,
|
||||
'isReply'=>$value['isReply']
|
||||
];
|
||||
|
||||
$id = $this->inbox_obj->insertGetId($insert);
|
||||
|
||||
if(!empty($value['url']) && is_array($value['url'])){
|
||||
$urls=[];
|
||||
foreach ($value['url'] as $k => $url){
|
||||
|
||||
$urls[$k]=[
|
||||
'emailId'=>$id,
|
||||
'attachmentUrl'=>$url
|
||||
];
|
||||
}
|
||||
$this->inbox_attachment_obj->insertAll($urls);
|
||||
}
|
||||
}
|
||||
|
||||
//提交事务
|
||||
Db::commit();
|
||||
} catch (\Exception $e) {
|
||||
// 回滚事务
|
||||
Db::rollback();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
425
extend/email/receiveMails.php
Normal file
425
extend/email/receiveMails.php
Normal file
@@ -0,0 +1,425 @@
|
||||
<?php
|
||||
namespace email;
|
||||
|
||||
use think\Env;
|
||||
|
||||
class receiveMails{
|
||||
|
||||
var $marubox='';
|
||||
|
||||
/**
|
||||
* 连接 邮箱
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
function connect($data) //Connect To the Mail Box
|
||||
{
|
||||
|
||||
$mailServer = Env::get('email.mail_server');
|
||||
|
||||
$mailLink="{{$mailServer}:143}" ; //imagp连接地址:不同主机地址不同
|
||||
|
||||
$mailUser = $data['email'];
|
||||
|
||||
$mailPass = $data['epassword'];
|
||||
|
||||
$this->marubox = imap_open($mailLink,$mailUser,$mailPass);
|
||||
|
||||
if (!$this->marubox) {
|
||||
|
||||
echo "Error: Connecting to mail server";
|
||||
exit;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取邮件数
|
||||
* @return false|int
|
||||
*/
|
||||
function getTotalMails()
|
||||
{
|
||||
if (!$this->marubox){
|
||||
return false;
|
||||
}
|
||||
$date = date("j F Y");
|
||||
$emails = imap_search($this->marubox,'SINCE "'.$date.'"');
|
||||
return $emails;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取邮件头部信息
|
||||
* @param $mid
|
||||
* @return array|false
|
||||
*/
|
||||
|
||||
function getHeaders($mid) // Get Header info
|
||||
{
|
||||
if (!$this->marubox){
|
||||
return false;
|
||||
}
|
||||
|
||||
$mail_header = imap_header($this->marubox, $mid);
|
||||
$sender = $mail_header->from[0];
|
||||
if (strtolower($sender->mailbox) != 'mailer-daemon' && strtolower($sender->mailbox) != 'postmaster') {
|
||||
|
||||
$subject = $this->decode_mime($mail_header->subject);
|
||||
$mail_details = array(
|
||||
|
||||
'emailId'=>$mid,
|
||||
'from' => strtolower($sender->mailbox) . '@' . $sender->host,
|
||||
'subject'=>$subject,//imap_mime_header_decode($mail_header->subject)[0]->text,
|
||||
'sendTime' => $mail_header->udate,
|
||||
'isReply'=>0
|
||||
|
||||
);
|
||||
|
||||
$reply = substr($mail_details['subject'],0,2);
|
||||
if($reply == 'RE' || $reply == 'Re' ){
|
||||
|
||||
$mail_details['isReply'] = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return $mail_details;
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理邮件附件
|
||||
* @param $mid
|
||||
* @return array|false
|
||||
*/
|
||||
function getAttach($mid) // Get Atteced File from Mail
|
||||
{
|
||||
if (!$this->marubox){
|
||||
return false;
|
||||
}
|
||||
$struckture = imap_fetchstructure($this->marubox, $mid);
|
||||
|
||||
$files = array();
|
||||
if ($struckture->parts) {
|
||||
|
||||
foreach ($struckture->parts as $key => $value) {
|
||||
$enc = $struckture->parts[$key]->encoding;
|
||||
|
||||
//取邮件附件
|
||||
if ($struckture->parts[$key]->ifdparameters) {
|
||||
|
||||
//命名附件,转码
|
||||
$name = $this->decode_mime($struckture->parts[$key]->dparameters[0]->value);
|
||||
|
||||
$extend = explode(".", $name);
|
||||
|
||||
$file['extension'] = $extend[count($extend) - 1];
|
||||
|
||||
$file['pathname'] = $this->setPathName($mid, $key, $file['extension']);
|
||||
|
||||
$file['title'] = !empty($name) ? htmlspecialchars($name) : str_replace('.' . $file['extension'], '', $name);
|
||||
|
||||
if (@$struckture->parts[$key]->disposition == "attachment") { // 是附件
|
||||
$path = ROOT_PATH.'public' . DS . 'downAttachment' . DS . date('Ymd') .DS;
|
||||
$file['type'] = 1;
|
||||
} else { // 是正文内容
|
||||
$file['type'] = 0;
|
||||
$path = ROOT_PATH.'public' . DS . 'contentImg' . DS . date('Ymd') .DS;
|
||||
}
|
||||
|
||||
$message = imap_fetchbody($this->marubox, $mid, $key + 1);
|
||||
if ($enc == 0){
|
||||
$message = imap_8bit($message);
|
||||
}
|
||||
if ($enc == 1){
|
||||
$message = imap_8bit($message);
|
||||
}
|
||||
if ($enc == 2){
|
||||
$message = imap_binary($message);
|
||||
}
|
||||
if ($enc == 3){//图片
|
||||
$message = imap_base64($message);
|
||||
}
|
||||
if ($enc == 4){
|
||||
$message = quoted_printable_decode($message);
|
||||
}
|
||||
if ($enc == 5){
|
||||
$message = $message;
|
||||
}
|
||||
|
||||
|
||||
if (!file_exists($path)){
|
||||
mkdir($path,0777,true);
|
||||
}
|
||||
$fp = fopen($path . $file['pathname'], "w+");
|
||||
fwrite($fp, $message);
|
||||
fclose($fp);
|
||||
|
||||
$file['url']=$path . $file['pathname'];
|
||||
|
||||
$files[] = $file;
|
||||
}
|
||||
|
||||
// 处理内容中包含图片的部分
|
||||
if($key == 0){
|
||||
|
||||
if (isset($struckture->parts[$key]->parts)) {
|
||||
|
||||
foreach ($struckture->parts[$key]->parts as $keyb => $valueb) {
|
||||
$enc = $struckture->parts[$key]->parts[$keyb]->encoding;
|
||||
if ($struckture->parts[$key]->parts[$keyb]->ifdparameters) {
|
||||
//命名图片
|
||||
$name = $this->decode_mime($struckture->parts[0]->parts[$keyb]->dparameters[0]->value);
|
||||
$extend = explode(".", $name);
|
||||
$file['extension'] = $extend[count($extend) - 1];
|
||||
$file['pathname'] = $this->setPathName($mid,$key, $file['extension'],0);
|
||||
$file['title'] = !empty($name) ? htmlspecialchars($name) : str_replace('.' . $file['extension'], '', $name);
|
||||
|
||||
// $file['size'] = $struckture->parts[$key]->parts[$keyb]->dparameters[1]->value;
|
||||
// $file['tmpname'] = $struckture->parts[$key]->dparameters[0]->value;
|
||||
|
||||
$file['type'] = 0;
|
||||
|
||||
|
||||
$partnro = ($key + 1) . "." . ($keyb + 1);
|
||||
|
||||
$message = imap_fetchbody($this->marubox, $mid, $partnro);
|
||||
if ($enc == 0){
|
||||
$message = imap_8bit($message);
|
||||
}
|
||||
if ($enc == 1){
|
||||
$message = imap_8bit($message);
|
||||
}
|
||||
if ($enc == 2){
|
||||
$message = imap_binary($message);
|
||||
}
|
||||
if ($enc == 3){
|
||||
$message = imap_base64($message);
|
||||
}
|
||||
if ($enc == 4){
|
||||
$message = quoted_printable_decode($message);
|
||||
}
|
||||
if ($enc == 5){
|
||||
$message = $message;
|
||||
}
|
||||
|
||||
$path = ROOT_PATH.'public' . DS . 'contentImg' . DS . date('Ymd') .DS;
|
||||
|
||||
if (!file_exists($path)){
|
||||
mkdir($path,0777,true);
|
||||
}
|
||||
|
||||
$fp = fopen($path . $file['pathname'], "w+");
|
||||
fwrite($fp, $message);
|
||||
fclose($fp);
|
||||
|
||||
$file['url']=$path . $file['pathname'];
|
||||
|
||||
$files[] = $file;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取正文
|
||||
* @param $mid
|
||||
* @param $path
|
||||
* @param $imageList
|
||||
* @return false|mixed|string|string[]|void
|
||||
*/
|
||||
function getBody($mid,$path,$imageList,$section) // Get Message Body
|
||||
{
|
||||
|
||||
if (!$this->marubox){
|
||||
return false;
|
||||
}
|
||||
|
||||
$struckture = imap_fetchstructure($this->marubox, $mid);
|
||||
|
||||
|
||||
if(isset($struckture->parts))
|
||||
{
|
||||
|
||||
if($struckture->subtype == 'MIXED' || $struckture->subtype == 'RELATED' ){
|
||||
$encoding= $struckture->parts[0]->parts[0]->encoding;
|
||||
}
|
||||
if($struckture->subtype == 'ALTERNATIVE'){
|
||||
$encoding = $struckture->parts[0]->encoding;
|
||||
}
|
||||
|
||||
$body = $this->contentDecoder($encoding,$mid,$section);
|
||||
|
||||
//处理图片
|
||||
$body = $this->embed_images($body, $path, $imageList);
|
||||
return $body;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private function contentDecoder($encoding, $num,$section) //$this->mbox, $num, $section
|
||||
{
|
||||
switch ($encoding) {
|
||||
case 0:
|
||||
case 1:
|
||||
$message = imap_8bit(imap_fetchbody($this->marubox, $num, $section));
|
||||
break;
|
||||
case 2:
|
||||
$message = imap_binary(imap_fetchbody($this->marubox, $num, $section));
|
||||
break;
|
||||
case 3:
|
||||
$message = iconv('gbk', 'utf-8',imap_base64(imap_fetchbody($this->marubox, $num, $section)));
|
||||
break;
|
||||
case 4:
|
||||
$message = quoted_printable_decode(imap_fetchbody($this->marubox, $num, $section));
|
||||
break;
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function embed_images(&$body,&$path,$imageList)
|
||||
{
|
||||
|
||||
// get all img tags
|
||||
preg_match_all('/<img.*?>/', $body, $matches);
|
||||
if (!isset($matches[0])) return;
|
||||
|
||||
foreach ($matches[0] as $key=>$img)
|
||||
{
|
||||
// halt($path.$imageList[$key]);
|
||||
// replace image web path with local path
|
||||
preg_match('/src="(.*?)"/', $img, $m);
|
||||
|
||||
if (!isset($m[1])) continue;
|
||||
$arr = parse_url($m[1]);
|
||||
if (!isset($arr['scheme']) || !isset($arr['path']))continue;
|
||||
|
||||
// if (!isset($arr['host']) || !isset($arr['path']))continue;
|
||||
if ($arr['scheme']!="http")
|
||||
{
|
||||
$filename=explode("@", $arr['path']);
|
||||
$body = str_replace($img, '<img alt="" src="'.$path.$imageList[$key].'" style="border: none;" />', $body);
|
||||
// $body = str_replace($img, '<img alt="" src="'.$path.$imageList[$filename[0]].'" style="border: none;" />', $body);
|
||||
}
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
function get_part($stream, $msg_number, $mime_type, $structure = false, $part_number = false) //Get Part Of Message Internal Private Use
|
||||
{
|
||||
|
||||
if (!$structure) {
|
||||
$structure = imap_fetchstructure($stream, $msg_number);
|
||||
}
|
||||
if ($structure) {
|
||||
if ($mime_type == $this->get_mime_type($structure)) {
|
||||
if (!$part_number) {
|
||||
$part_number = "1";
|
||||
}
|
||||
$text = imap_fetchbody($stream, $msg_number, $part_number);
|
||||
|
||||
if ($structure->encoding == 3) {
|
||||
return imap_base64($text);
|
||||
// if ($structure->parameters[0]->value!="utf-8")
|
||||
// {
|
||||
// return imap_base64($text);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return imap_base64($text);
|
||||
// }
|
||||
} else if ($structure->encoding == 4) {
|
||||
return iconv('gb2312', 'utf8', imap_qprint($text));
|
||||
} else {
|
||||
return iconv('gb2312', 'utf8', $text);
|
||||
}
|
||||
}
|
||||
if ($structure->type == 1) /* multipart */ {
|
||||
while (list($index, $sub_structure) = $this->new_each($structure->parts)) {
|
||||
if ($part_number) {
|
||||
$prefix = $part_number . '.';
|
||||
}else{
|
||||
$prefix = "1";
|
||||
}
|
||||
$data = $this->get_part($stream, $msg_number, $mime_type, $sub_structure, $prefix . ($index + 1));
|
||||
if ($data) {
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function get_mime_type(&$structure) //Get Mime type Internal Private Use
|
||||
{
|
||||
$primary_mime_type = array("TEXT", "MULTIPART", "MESSAGE", "APPLICATION", "AUDIO", "IMAGE", "VIDEO", "OTHER");
|
||||
|
||||
if($structure->subtype && $structure->subtype!="PNG") {
|
||||
return $primary_mime_type[(int) $structure->type] . '/' . $structure->subtype;
|
||||
}
|
||||
return "TEXT/PLAIN";
|
||||
}
|
||||
|
||||
function new_each(&$array){
|
||||
$res = array();
|
||||
$key = key($array);
|
||||
if($key !== null){
|
||||
next($array);
|
||||
$res[1] = $res['value'] = $array[$key];
|
||||
$res[0] = $res['key'] = $key;
|
||||
}else{
|
||||
$res = false;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 标题编码转化
|
||||
* @param $str
|
||||
* @return false|string
|
||||
*/
|
||||
function decode_mime($str)
|
||||
{
|
||||
$str = imap_mime_header_decode($str);
|
||||
|
||||
return $str[0]->text;
|
||||
|
||||
if ($str[0]->charset != "default") {
|
||||
|
||||
return iconv($str[0]->charset, 'utf8', $str[0]->text);
|
||||
} else {
|
||||
return $str[0]->text;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set path name of the uploaded file to be saved.
|
||||
*
|
||||
* @param int $mid
|
||||
* @param int $fileID
|
||||
* @param string $extension
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function setPathName($mid, $fileID, $extension,$type = 1)
|
||||
{
|
||||
if($type == 1){
|
||||
return $mid."-".$fileID .'.' . $extension;
|
||||
}else{
|
||||
return $mid."-".$fileID .mt_rand(0, 10000) .'.' . $extension;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user