
/*=============================================================================================
	author:ZhaoJun
	version:1.2
	email:2732810281@qq.com
=============================================================================================*/


//严格模式
/*-------------------------------------------------------------------------------------------*/	
'use strict';
/*-------------------------------------------------------------------------------------------*/
    
// 复用的操作
/*-------------------------------------------------------------------------------------------*/	
	class email
	{
		//发送邮箱
		static async send({html='',title='',to})
		{
			let con=await $Sys.model('/socket/client','connect')({port:$ToolMail.port,host:$ToolMail.host});
			if(con)
			{
				con.setEncoding('utf8');
				let data=await email.pro(con);
				let result=email.com(con,data,'220','HELO email\r\n','[邮件发送]握手，发送失败','[邮件发送]链接,返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				result=email.com(con,data,'250','AUTH LOGIN\r\n','[邮件发送]授权，发送失败','[邮件发送]握手，返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				result=email.com(con,data,'334',Buffer.from($ToolMail.user).toString('base64')+'\r\n'
							,'[邮件发送]授权用户名，发送失败','[邮件发送]授权，返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				result=email.com(con,data,'334',Buffer.from($ToolMail.pass).toString('base64')+'\r\n'
							,'[邮件发送]授权密码，发送失败','[邮件发送]授权用户名，返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				result=email.com(con,data,'235',`MAIL FROM:<${$ToolMail.user}>\r\n`
							,'[邮件发送]邮箱发送者设置，发送失败','[邮件发送]授权密码，返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				result=email.com(con,data,'250',`RCPT TO:<${to}>\r\n`
							,'[邮件发送]邮箱接收者设置，发送失败','[邮件发送]邮箱发送者设置，返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				result=email.com(con,data,'250','DATA\r\n'
							,'[邮件发送]邮箱准备发信，发送失败','[邮件发送]邮箱接收者设置，返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				let content='From: '+$ToolMail.user+
				'\r\nTo: '+to+'\r\n'+
				'Subject: '+title+
				'\r\nX-Mailer: Microsoft Outlook Express 6.00.2900.2869\r\n'+
				'Content-type: text/html; charset=utf-8\r\nContent-Transfer-Encoding: base64\r\n\r\n'+
				Buffer.from(html).toString('base64')+
				'\r\n.\r\n';
				result=email.com(con,data,'354',content,'[邮件发送]邮箱发信，发送失败','[邮件发送]邮箱准备发信，返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				result=email.com(con,data,'250',null,'','[邮件发送]邮箱发信，返回失败');
				return result;
			}
			else
			{	
				return $Sys.model('/fun/filter','echo')(false,"[邮件发送]链接失败");
			}
		}

		//接收邮箱
		static async receive(id)
		{
			let con=await $Sys.model('/request/public','connect')({port:$ToolMail.port_imap,host:$ToolMail.host_imap});
			if(con)
			{
				con.setEncoding('utf8');
				let data=await email.pro(con);
				let result=email.com(con,data,'OK',`A01 LOGIN ${$ToolMail.user} ${$ToolMail.pass}\r\n`,
								'[邮件接收]登陆，发送失败','[邮件接收]链接,返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				result=email.com(con,data,'OK',`A03 Select INBOX\r\n`
							,'[邮件接收]选择邮箱，发送失败','[邮件接收]登陆，返回失败');
				if(result.code)
				{
					return result;
				}
				data=await email.pro(con);
				let get=async (tag)=>
				{
					result=email.com(con,data,'OK',`A05 Search new\r\n`,
					'[邮件接收]选择未读邮箱，发送失败','[邮件接收]选择邮箱，返回失败',
					tag);
					if(result.code)
					{
						return result;
					}
					data=await email.pro(con,'A05 OK'); 
					result=email.com(con,data,'* SEARCH',false
								,'','[邮件接收]选择未读邮箱，返回失败',tag);	
					return result;
				}
				let ec=async (id,tag)=>
				{
					id=parseInt(id);
					if(typeof id != 'number')
					{
						return $Sys.model('/fun/filter','echo')(false,'[邮件接收]邮箱数据id不为数字')
					}
					result=email.com(con,data,'OK',`A07 Fetch ${id} rfc822\r\n`,
					'[邮件接收]读取邮箱，发送失败','[邮件接收]选择邮箱，返回失败',tag);
					if(result.code)
					{
						return result;
					}
					data=await email.pro(con,'A07 OK');
					result=email.com(con,data,'A07 OK Fetch',null,
					'','[邮件接收]选择未读邮箱，返回失败',tag);
					return email.parse(result.data);
				} 
				if(id)
				{
					if(id instanceof Function)
					{
						let result=await get(true);
						if(result.stat && (result.data instanceof Array))
						{
							let loop;
							let arr=result.data;
							result.data={};
							while(loop=arr.pop())
							{
								let su=await ec(loop,true)
								if(su.content)
								{
									let back=await id(su,result.data);
									if(back===true)
									{
										con.destroy();
										return result;
									}
								}
							}
						}
						con.destroy();
						return result;
					}
					else
					{
						return ec(id)
					}
				}
				else
				{
					return get();
				}
			}
			else
			{
				return $Sys.model('/fun/filter','echo')(false,'[邮件接收]链接失败');
			}
		}

		static parse(str)
		{
			var content=str.split(/\r\n\r\n/).pop()
			if(content)
			{
				content=content.split('\r\n--').shift();
			}
			var from=str.match(/From:.*?<(.*?)>/);
			if(from)
			{
				from=from[1];
			}
			return {source:str,content:content,
					parse:Buffer.from(content,'base64').toString(),
					from:from}
		}

		static pro(con,code) 
		{
			return (new Promise((reslove,reject)=>
			{
				if(code)
				{
					let str='';
					con.on('data',data=>
					{
						str+=data;
						if(data.includes(code))
						{
							con.removeAllListeners('data')
							reslove(str)
						}
					});
				}
				else
				{
					con.once('data',data=>
					{
						reslove(data)
					});
				}
				let ti=setTimeout(()=>
				{
					reject('邮件超时')
				},6000) 
				ti.unref();
			}))
		}

		static com(con,data,code,se,mes,mes1,tag)
		{
			if(data.includes(code))
			{
				if(se)
				{
					if(con.sender(se))
					{
						return $Sys.model('/fun/filter','echo',{check:true,message:'失败'})
					}
					else
					{
						return $Sys.model('/fun/filter','echo',[{check:false,message:mes}]);
					}
				}
				else
				{
					if(!tag)
					{
						con.destroy();
					}
					if(se===null)
					{
						return $Sys.model('/fun/filter','echo',[{check:data,message:'失败'}]);
					}
					else
					{
						let str=data.split('* SEARCH')[1];
						if(str)
						{
							return $Sys.model('/fun/filter','echo')
							(
								[
									{
										check:str.split('\r\n')[0].split(' ').slice(1),
										message:'未读邮件为空'
									}
								]
							)
						} 
						else
						{
							return $Sys.model('/fun/filter','echo',[{check:data,message:'失败'}])
						}
					}
				}
			}
			else
			{
				return $Sys.model('/fun/filter','echo',[{check:false,message:'失败'}]);
			}
		}
  	}
/*-------------------------------------------------------------------------------------------*/    
module.exports=email;