【PHP基础知识】——操作Email

邮件已经成为我们生活中不可或缺的信息沟通方式,时常需要我们去群发或者定时发送一下邮件给指定对象,例如系统的故障报警邮件,批量回复一些服务信息等。因此,将发送邮件功能做到后台可配置或者自动化是程序开发的重要部分。像Java等语言一样,下面我们也来罗列一下PHP操作Email的发送和接收功能。

一、邮件服务协议

1、简单邮件传输协议(SMTP) 是一个相对简单的基于文本的协议。在其之上指定了一条消息的一个或多个接收者(在大多数情况下被确认是存在的),然后消息文本会被传输。可以很简单地通过telnet程序来测试一个SMTP服务器。SMTP默认使用TCP端口25。

2、POP3协议:负责从邮件服务器中检索电子邮件。它要求邮件服务器完成下面几种任务之一:从邮件服务器中检索邮件并从服务器中删除这个邮件;从邮件服务器中检索邮件但不删除它;不检索邮件,只是询问是否有新邮件到达。POP协议支持传输任何格式的文件,包括图片和声音文件等。在用户阅读邮件时,POP命令所有的邮件信息立即下载到用户的计算机上,不在服务器上保留

3、IMAP协议:互联网信息访问协议(IMAP)是一种优于POP的新协议。和POP一样,IMAP也能下载邮件、从服务器中删除邮件或询问是否有新邮件,但IMAP克服了POP的一些缺点。例如,它可以决定客户机请求邮件服务器提交所收到邮件的方式,请求邮件服务器只下载所选中的邮件而不是全部邮件。客户机可先阅读邮件信息的标题和发送者的名字再决定是否下载这个邮件。通过用户的客户机电子邮件程序,IMAP可让用户在服务器上创建并管理邮件文件夹或邮箱、删除邮件、查询某封信的一部分或全部内容,完成所有这些工作时都不需要把邮件从服务器下载到用户的个人计算机上。

二、终端命令行操作邮件服务器的方式

1、通过tls方式连接邮件服务器和发送邮件:telnet <域名> <端口>
通过以上命令即可访问到邮件服务器,并请求连接,具体连接过程示例如下:
①telnet <域名> 25
返回220 Anti-spam GT for Coremail System 

②helo localhost    //helo 向服务器发出标志自己身份的命令
返回250 OK 

③auth login        //用于请求认证和连接邮件服务器
返回334 dXNlcm5hbWU6 //后面那一串是base64encode后的字符串,解码后是username

④输入base64编码后的用户名
返回334 UGFzc3dvcmQ6 //后面那一串是base64encode后的字符串,解码后是password

⑤输入base64编码后的密码
返回235 Authentication successful        //连接成功

⑥mail
 from:<yourmailaddress>        //注释邮件发送者
返回250 Mail OK

⑦rcpt
 to:<dstmailaddress>            //注释邮件接收者
返回250 Mail OK

⑧data                    //data命令开始书写邮件内容
to:dstmailaddress        //收件人邮箱跟上文保持一致
from:yourmailaddress    //发件人邮箱跟上文保持一致
subject:test
mail
//空一行
This is a test mail….
//空一行
.                    //注释:<点>+<回车> 正文内容结束标志
返回250 Mail OK queued as smtp12,EMCowABnovABxQ1XZjKTAQ--.7259S2 1460520311

⑨退出:quit

2、通过ssl方式连接和操作邮件服务器发送邮件:
openssl s_client -connect servername:端口号(默认465)
第②步开始和tls连接方式一致。

ssl和tls方式的差别:
SSL是Netscape开发的专门用户保护Web通讯的,目前版本为3.0。最新版本的TLS 1.0是IETF(工程任务组)制定的一种新的协议,它建立在SSL 3.0协议规范之上,是SSL 3.0的后续版本。两者差别极小,可以理解为SSL 3.1,它是写入了RFC的。 

流程图(引用)如下:


两者的端口如下:


三、PHP操作请求邮件服务器

1、使用tls发送邮件:

class SMTP {

	var $connection;
	var $recipients;
	var $headers;
	var $timeout;
	var $errors;
	var $status;
	var $body;
	var $from;
	var $host;
	var $port;
	var $helo;
	var $auth;
	var $user;
	var $pass;

	/**
	 *  参数为一个数组
	 *  host        SMTP 服务器的主机       默认:localhost
	 *  port        SMTP 服务器的端口       默认:25
	 *  helo        发送HELO命令的名称      默认:localhost
	 *  user        SMTP 服务器的用户名     默认:空值
	 *  pass        SMTP 服务器的登陆密码   默认:空值
	 *  timeout     连接超时的时间          默认:5
	 * @return  bool
	 */
	function SMTP($params = array()) {

		if (!defined('CRLF')) {
			define('CRLF', "\r\n", true);
		}

		$this->timeout = 10;
		$this->status = 1;
		$this->host = 'localhost';
		$this->port = 25;
		$this->auth = false;
		$this->user = '';
		$this->pass = '';
		$this->errors = array();

		foreach ($params AS $key => $value) {
			$this->$key = $value;
		}

		$this->helo = $this->host;

		//  如果没有设置用户名则不验证
		$this->auth = ('' == $this->user) ? false : true;

	}

	function connect($params = array()) {

		if (!isset($this->status)) {
			$obj = new SMTP($params);

			if ($obj->connect()) {
				$obj->status = 2;
			}

			return $obj;
		} else {
			$this->connection = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout);
			@socket_set_timeout($this->connection, 0, 250000);

			$greeting = $this->get_data();
			if (is_resource($this->connection)) {
				$this->status = 2;
				return $this->auth ? $this->ehlo() : $this->helo();
			} else {
				$this->errors[] = 'Failed to connect to server: ' . $errstr;
				return false;
			}
		}
	}

	/**
	 * 参数为数组
	 * recipients      接收人的数组
	 * from            发件人的地址,也将作为回复地址
	 * headers         头部信息的数组
	 * body            邮件的主体
	 */

	function send($params = array()) {

		foreach ($params AS $key => $value) {
			$this->set($key, $value);
		}

		if ($this->is_connected()) {
			//  服务器是否需要验证
			if ($this->auth) {
				if (!$this->auth()) {
					return false;
				}
			}

			$this->mail($this->from);

			if (is_array($this->recipients)) {
				foreach ($this->recipients AS $value) {
					$this->rcpt($value);
				}
			} else {
				$this->rcpt($this->recipients);
			}

			if (!$this->data()) {
				return false;
			}

			$headers = str_replace(CRLF . '.', CRLF . '..', trim(implode(CRLF, $this->headers)));
			$body = str_replace(CRLF . '.', CRLF . '..', $this->body);
			$body = $body[0] == '.' ? '.' . $body : $body;

			$this->send_data($headers);
			$this->send_data('');
			$this->send_data($body);
			$this->send_data('.');

			return (substr($this->get_data(), 0, 3) === '250');

		} else {
			$this->errors[] = 'Not connected!';
			return false;
		}
	}

	function helo() {
		if (is_resource($this->connection)
			AND $this->send_data('HELO ' . $this->helo)
				AND substr($error = $this->get_data(), 0, 3) === '250'
		) {
			return true;
		} else {
			$this->errors[] = 'HELO command failed, output: ' . trim(substr($error, 3));
			return false;
		}
	}

	function ehlo() {
		if (is_resource($this->connection)
			AND $this->send_data('EHLO ' . $this->helo)
				AND substr($error = $this->get_data(), 0, 3) === '250'
		) {
			return true;
		} else {
			$this->errors[] = 'EHLO command failed, output: ' . trim(substr($error, 3));
			return false;
		}
	}

	function auth() {
		if (is_resource($this->connection)
			AND $this->send_data('AUTH LOGIN')
				AND substr($error = $this->get_data(), 0, 3) === '334'
					AND $this->send_data(base64_encode($this->user)) // Send username
						AND substr($error = $this->get_data(), 0, 3) === '334'
							AND $this->send_data(base64_encode($this->pass)) // Send password
								AND substr($error = $this->get_data(), 0, 3) === '235'
		) {
			return true;
		} else {
			$this->errors[] = 'AUTH command failed: ' . trim(substr($error, 3));
			return false;
		}
	}

	function mail($from) {
		if ($this->is_connected()
			AND $this->send_data('MAIL FROM:<' . $from . '>')
				AND substr($this->get_data(), 0, 2) === '250'
		) {
			return true;
		} else {
			return false;
		}
	}

	function rcpt($to) {
		if ($this->is_connected()
			AND $this->send_data('RCPT TO:<' . $to . '>')
				AND substr($error = $this->get_data(), 0, 2) === '25'
		) {
			return true;
		} else {
			$this->errors[] = trim(substr($error, 3));
			return false;
		}
	}

	function data() {
		if ($this->is_connected()
			AND $this->send_data('DATA')
				AND substr($error = $this->get_data(), 0, 3) === '354'
		) {
			return true;
		} else {
			$this->errors[] = trim(substr($error, 3));
			return false;
		}
	}

	function is_connected() {
		return (is_resource($this->connection) && ($this->status === 2));
	}

	function send_data($data) {
		if (is_resource($this->connection)) {
			return fwrite($this->connection, $data . CRLF, strlen($data) + 2);
		} else {
			return false;
		}
	}

	function get_data() {
		$return = '';
		$line = '';

		if (is_resource($this->connection)) {
			while (strpos($return, CRLF) === false OR $line{3} !== ' ') {
				$line = fgets($this->connection, 512);
				$return .= $line;
			}

			return trim($return);
		} else {
			return '';
		}
	}

	function set($var, $value) {
		$this->$var = $value;
		return true;
	}

	/**
	 * 获得最后一个错误信息
	 *
	 * @access  public
	 * @return  string
	 */
	function error_msg() {
		if (!empty($this->errors)) {
			$len = count($this->errors) - 1;
			return $this->errors[$len];
		} else {
			return '';
		}
	}

}


2、使用ssl发送邮件:
和tls一致,只需要在@fsockopen()方法的host参数前面加上'ssl://'的字符串即可,当然端口要改为465。

3、接收邮件

邮件接收可分为POP3和IMAP协议两种,具体方法可参照:https://my.oschina.net/idufei/blog/40150


4、附上SMTP类的调用方法:

//将邮件参数配置写在$GLOBALS['MAIL_CONFIG']数组里,在框架入口引入即可。
class Mailer {

	private $smtpHost;
	private $smtpPort;
	private $smtpSSL;
	private $smptAuthUser;
	private $smtpAuthPassword;
	private $fromName;
	private $fromEmail;

	public function __construct($config = null) {

		$config = $config ? $config : $GLOBALS['MAIL_CONFIG'];
		$this->smtpHost = $config['SMTP_HOST'];
		$this->smtpPort = $config['SMTP_PORT'];
		$this->smptAuthUser = $config['SMTP_AUTH_USER'];
		$this->smtpAuthPassword = $config['SMTP_AUTH_PASSWORD'];
		$this->fromName = $config['FROM_NAME'];
		$this->fromEmail = $config['FROM_EMAIL'];

	}

	/**
	 * 发送邮件
	 * @param  $toName 收件人名称
	 * @param  $toEmail 收件人邮箱
	 * @param  $subject 主题
	 * @param  $content 内容
	 * @param int $contentType 信件内容类型 0-text/plain 1-text/html
	 * @param string $fromName 发信人名称
	 * @param string $fromEmail 发信人邮箱
	 * @return bool
	 */
	public function sendMail($toName, $toEmail, $subject, $content, $contentType = 0, $fromName = '', $fromEmail = '') {

		$charset = 'utf-8';

		if (!$fromName) $fromName = $this->fromName;
		if (!$fromEmail) $fromEmail = $this->fromEmail;

		/* 邮件的头部信息 */
		$content_type = ($contentType == 0) ? 'Content-Type: text/plain; charset=' . $charset : 'Content-Type: text/html; charset=' . $charset;
		$content = base64_encode($content);

		$headers[] = 'Date: ' . gmdate('D, j M Y H:i:s') . ' +0000';
		$headers[] = 'To: "' . '=?' . $charset . '?B?' . base64_encode($toName) . '?=' . '" <' . $toEmail . '>';
		$headers[] = 'From: "' . '=?' . $charset . '?B?' . base64_encode($fromName) . '?=' . '" <' . $fromEmail . '>';
		$headers[] = 'Subject: ' . '=?' . $charset . '?B?' . base64_encode($subject) . '?=';
		$headers[] = $content_type . '; format=flowed';
		$headers[] = 'Content-Transfer-Encoding: base64';
		$headers[] = 'Content-Disposition: inline';

		/* 获得邮件服务器的参数设置 */
		$params['host'] = $this->smtpHost;
		$params['port'] = $this->smtpPort;
		$params['user'] = $this->smptAuthUser;
		$params['pass'] = $this->smtpAuthPassword;

		if (empty($params['host']) || empty($params['port'])) {
			die("No SMTP Host!");
		} else {

			// 发送邮件
			static $smtp;

			$send_params['recipients'] = $toEmail;
			$send_params['headers'] = $headers;
			$send_params['from'] = $fromEmail;
			$send_params['body'] = $content;

			if (!isset($smtp)) {
				$smtp = new SMTP($params);
			}

			if ($smtp->connect() && $smtp->send($send_params)) {
				return true;
			} else {
				echo $smtp->error_msg();
				return false;
			}
		}

	}

}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
receivemail是一个专门用来接收邮件PHP类,支持POP3和IMAP等邮件协议。 可以接收邮件邮件附件。 include("receivemail.class.php"); 02 // 创建一个 reciveMail 对象 03 $obj = new receiveMail('[email protected]','xxxxxx','[email protected]','pop.abc.com','pop3','110',false); 04 // 连接到邮件服务器 05 $obj->connect(); //If connection fails give error message and exit 06 // 读取未读邮件数 07 $tot = $obj->getTotalMails(); //Total Mails in Inbox Return integer value 08 09 echo "收到$tot封邮件::"; 10 for($i = $tot; $i > 0; $i--) 11 { 12 $head = $obj->getHeaders($i); // 读取获取邮件头信息,返回数组 **数组键值为 (subject,to,toOth,toNameOth,from,fromName) 13 echo "主题 :: ".$head['subject'].""; 14 echo "收件人 :: ".$head['to'].""; 15 echo "抄送 :: ".$head['toOth'].""; 16 echo "发件人 :: ".$head['from'].""; 17 echo "发件人名称 :: ".$head['fromName'].""; 18 echo ""; 19 echo "*******************************************************************************************"; 20 echo $obj->getBody($i); // 邮件正文 21 $str = $obj->GetAttach($i,"./"); // 获取邮件附件,返回的文件名以逗号隔开。 例如. (mailid, Path to store file) 22 $ar = explode(",",$str); 23 foreach($ar as $key=>$value) 24 echo ($value == "") ? "" : "Atteched File :: " . $value . ""; 25 echo "------------------------------------------------------------------------------------------"; 26 //$obj->deleteMails($i); // Delete Mail from Mail box 27 } 28 $obj->close_mailbox(); //Close Mail Box

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值