用PHP通过SMTP发送邮件

 更新时间:2016年11月25日 17:02  点击:1274

由于PHP没有提供现成的smtp函数,却提供了一个功能不甚灵活的mail()函数,这个函数需要服务器配置上的支持,并且不支持smtp验证,在很多场合无法正常的工作,因此不建议使用。本文的目的在于为新手指明方向,并没有涉及那些高级的内容,一来本身水平有限,二来也担心不能准确的讲述相关的概念,进而对各位造成误导,还请自行深入学习。

  “使用php发送mail”最近已经成为继“register_globals”以后本版第二个新手陷阱,今天特地写这篇文章为新手解惑,希望可以为迷茫的人指明方向。

  让我们先从以下这个例子开始说起:

  引用:

[root@server~/]# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 server.domain.com.br ESMTP Postfix (2.1.0)
MAIL FROM: teste@dominio.com.br
250 Ok
RCPT TO: teste@dominio.com.br
250 Ok
DATA
354 End data with <CR><LF>.<CR><LF>
teste
.
250 Ok: queued as 7B41F4665A
QUIT
221 Bye
Connection closed by foreign host.

  注:以上来自netkiller的postfix文档,偷懒,直接用现成的。

  首先是使用telnet来连接本地的25端口,稍微熟悉点网络的人都知道smtp协议使用25端口,这也就是说,现在在连接本地的smtp服务器。

  引用:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 server.domain.com.br ESMTP Postfix (2.1.0)

  这些东西是系统输出信息,说明已经连接上了,而且这个smtp服务器是postfix做的。

  “MAIL FROM: teste@dominio.com.br”这个命令指明了发件地址是teste@dominio.com.br,“250 Ok”说明这条命令被服务器接受并正确执行,这类似http协议的200、404、500等状态代码。接下来的“RCPT TO: teste@dominio.com.br”指明了收件地址是teste@dominio.com.br。

  引用:

DATA
354 End data with <CR><LF>.<CR><LF>
teste
.

  这一段是输入邮件正文,输入“DATA”以后系统提示使用“<回车>.<回车>”来结束输入,正文内容是“teste”。

  最后使用“QUIT”退出。


  注:以上来自netkiller的postfix文档,偷懒,直接用现成的。

  首先是使用telnet来连接本地的25端口,稍微熟悉点网络的人都知道smtp协议使用25端口,这也就是说,现在在连接本地的smtp服务器。

  引用:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 server.domain.com.br ESMTP Postfix (2.1.0)

  这些东西是系统输出信息,说明已经连接上了,而且这个smtp服务器是postfix做的。

  “MAIL FROM: teste@dominio.com.br”这个命令指明了发件地址是teste@dominio.com.br,“250 Ok”说明这条命令被服务器接受并正确执行,这类似http协议的200、404、500等状态代码。接下来的“RCPT TO: teste@dominio.com.br”指明了收件地址是teste@dominio.com.br。

  引用:

DATA
354 End data with <CR><LF>.<CR><LF>
teste
.

  这一段是输入邮件正文,输入“DATA”以后系统提示使用“<回车>.<回车>”来结束输入,正文内容是“teste”。

  最后使用“QUIT”退出。

  注:以上来自netkiller的postfix文档,偷懒,直接用现成的。

最近有一个读者问我关于ThickBook新闻列表中处理订阅/退订的机制,并且是如何与实际的发送信息相配合,给邮件列表中的所有收信人的。问题提的不错,有一个相当轻易的方法,但是我首先要说的是我所做的没有任何投机取巧的地方,因为我非常的酷----就是有,我使用这个方法也只是因为我懒。注重,在市面上有非常多的邮件列表软件,可以把它装在系统上,并且也有一些别的,更多的是结合在一起的脚本集,你 也可以用来做同样的事情。但是,正如我所说,我是一个懒人,不想下载和安装任何东西,所以我生成了几 个相当简单的页面,用来执行我所要求的工作。很希望,有人能从中学到一些东西。

首先是订阅/退订脚本,它所做的工作就是从数据库表中增加或删除记录。把它叫做"manage.phtml" 或 差不多的什么东西。这样呢,就需要后台是某种数据库,在上面可以创建订阅表。根据政治中的半数原则,所以我将使用MySQL作为这个例子的数据库。你可以使用任何你常用的数据库,只是据PHP手册替换正确的数据库相关函数。

在我的订阅表中,我使用了两个字段:邮件地址(email_addr)和添加日期(date_added)。你可以根据需要增加字段,或者将date_added字段删除。在这个例子中,我只是向你展示我做了什么,你可以适当的进行 修改。在我的订阅表中,email_addr字段是一个不重复字段,意味着你不能增加另一个与之完全一样的e-mail 地址。这个可以避免重复订阅,而且当用户想退订时,也使删除记录的方法变得简单和可靠。

那么,让我们创建订阅/退订表单吧(manager.phtml或你想起的什么名字)。我使用同一个文件处理订阅和退订,也包括表格自身的动作,所以可能有点复杂。我将从头到尾讲解,然后把所有的片段组合在一起,放在一个表单中。

在脚本的开始处,是打开数据库和预备时间戳。在开始时处理这些不显眼的东西总是可以为我减轻一点压力。

--------------------------------------------------------------------------------
// 连接数据库
$db = mysql_connect("servername", "username", "password") or die ("不能连接。");

mysql_select_db("yourDB", $db) or die ("不能选择数据库。");

// 得到时间戳
$add_date = date("Y-m-d"); --------------------------------------------------------------------------------
  我们希望$op的值是"ds"。它不是复杂的程序缩写----我创的,表示"do something(做某事)" 。所以,脚本的第一件事就是查看$op的值是不是等于"ds"。这个值只有当表单被提交后才会被发送上来。所以假如$op的值不是"ds",那么说明用户还没有看过表单,所以应该把表单显示出来:

--------------------------------------------------------------------------------
if ($op != "ds") {

//需要订阅/退订

$text_block = "

<form name="form" method=post action="$PHP_SELF">
<input type=hidden name=op value=ds>

<p><strong>your e-mail address:</strong><br>
<input type=text name="email" size=25></p>

<p><strong>action:</strong><br>
<input type=radio name="action" value="sub" checked> sub
<input type=radio name="action" value="unsub"> unsub</p>

<P><input type=submit name="submit" value="do it"></p>
</form>

";

}--------------------------------------------------------------------------------
你会注重到我把文本放在$text_block变量中。通过把文本放在一个变量中,接下来我所要做的就是在后面在主HTML模板内输出$text_block的值。这是个人习惯问题,你可以根据你喜欢的时间和方式输出文本。

这个表单的动作是$PHP_SELF ,可以想象一下,它的意思就是当按下了提交按钮之后,它将会被重新装入。然后,你可以看到这个表单有三个字段:一个隐藏字段,用于给$op赋值为"ds" ;一个文本字段,叫做"email",在这里用户将填入他或她的email地址;还有一个是单选按钮集,叫做"action",根据它,用户可以决定执行哪一个动作(订阅或退订)。

在表单被提交之后,$op将等于"ds",并且$action的值将包含"sub"或"unsub"。那么,我们继续看上面 的if...语句,一旦提交,它将被跳过(因为$op=="ds")。假如$op的值为"ds"并且$action的值"sub"(订阅),下面的else if...句被执行。这段代码检查e-mail是否已经存在于订阅表中,假如不存在则将其插入到表中并打印出响应,否则忽略。

--------------------------------------------------------------------------------
else if (($op == "ds") && ($action == "sub")) {

// 检查邮件还未提交则提交它们,否则返回信息

$check = "select email_addr from subscribers
where email_addr = "$email"";

$check_result = mysql_query($check)
or die("不能执行地e-mail地址的检查。");

$check_num = mysql_num_rows($check_result);


if ($check_num == 0) {

// 假如$check_num为0,则没有找到匹配的记录,用户应该被提交

$sql = "insert into subscribers
values("$email", "$add_date")";


@mysql_query($sql) or die ("Couldn't insert email.");

$text_block = "
<P>感谢您的注册!</p>

<?php

class popMail
{
var $user='123@tom.com';
var $pwd='1234';
var $popFp;
var $msg;
var $welcome = '欢迎使用PHP接收邮件!';
function popMail($popHost='pop.tom.com',$popPort=110)
{
$this->msg = array();
$this->msg[] = $this->welcome;
if ( $this->openPop($popHost,$popPort))
{
$this->msg[] = 'pop server connect success!';
}else{
print_r( $this->msg );
}
}
function checkCommon($com,$msg)
{
echo $cod = empty($com)? $this->getServerMsg() : $this->putServerMsg( $com );
$this->msg[] = ereg( "^ OK" ,$cod )? $msg : $com .' exec is fauiler!error:'.$cod ;
if( !ereg( "^ OK" ,$cod ) )
{
echo $cod;
print_r($this->msg);
$this->closeStmp();
exit(0);
}
}
function init()
{
$greeting='';
$rn=' ';
//$this->checkCommon('',"connect");
//echo $this->putServerMsg("APOP ".$this->user ." ".$this->pwd.$rn);
// $this->checkCommon("USER ",'user');
echo $this->putServerMsg("USER $this->user".$rn);
echo $this->putServerMsg("PASS $this->pwd".$rn);
print_r( $this->msg );
}
function openPop($popHost,$popPort=110)
{
if( empty($popHost) )
{
$this->msg[] = 'pop host is null!';
return false;

我经常听到这样一个问题:"我有一个从网站发来的合同。我如何给通过表单发送的电子邮件增加一个附件呢?" 首先我要说的是要做到这个没有什么简单的办法。你要很好的理解PHP或其它的服务器端的脚本语言。当然你还要一个真正支持PHP的网站的账号。假如满足了这个前提,在你读完了本章后就可以用PHP发送带附件的电子邮件了。

  1. 附件是如何工作的

  假如你曾经在PHP的手册中搜索过"附件"函数,那么结果可能是什么都没有(至少在我写本文的时间还没有)。后来你就要花很多时间来了解这方面的知识。你也许会想当你给某个人发送一封带附件的电子邮件时,附件是和邮件一起放到收件人的信箱里的(比如,假如你给他/她发了一个PNG的图片文件,他/她的信箱里会包含一个txt文件(电子邮件)和一个.png文件(附件))。但这不是它的工作原理。当你加入一个附件时,你的邮件程序把附件转换成纯文本文件,并在你写的内容(实际的电子邮件)后面插入这个文本块。这个,当你把所有的东西发出来后,收件人的信箱里只有一个纯文本文件--一个同时包含附件和实际电子邮件内容的文件。

  下面是一个带附件(一个HTML文件)电子邮件的例子。我已经标注了其中重要的几行:

Return-Path: <someone@example.com>
Date: Thurs, 10 June 2004 8:17:29 0000
From: Someone <someone@example.com>
To: Person <web@>
Message-id: <web@>
Content-type: multipart/mixed; boundary="web"
Subject: Here's the subject



--web
Content-type: text/plain; charset=g2312
Content-transfer-encoding: 8bit

This is the body of the email.

--web
Content-type: text/html; name=attachment.html
Content-disposition: inline; filename=attachment.html
Content-transfer-encoding: 8bit

<html>
<head>
<title>The attachment</title>
</head>
<body>
<h2>This is the attached HTML file</h2>
</body>
</html>

--396d983d6b89a--

前面的7行是邮件的头,其中值得注重的是Content-type头部分。这个头告诉邮件程序电子邮件是由一个以上的部分组成的。不含附件的邮件只有一个部分:消息本身。带附件的电子通常至少由两部分组成:消息和附件。这样,带两个附件的邮件由三部分组成:消息,第一个附件和第二个附件。

带附件的电子邮件的不同部分之间用分界线来分隔。分界线在Content-type头中定义。邮件的每个新部分以两个连字号(--)和分界线开始。最后一个分界线后也有两个连字号,表示这个邮件中没有其它的部分了。

在每个分界线后有一些行,用来告诉邮件程序这个部分的内容的类型。比如,看看上面例子中第一个分界线后面的两行--以Content-type: text/plain开头的行。这些行说明后面的部分是ISO-8859-1字符集的纯文本。跟在第二个分界线后的行告诉邮件程序现在的部分是一个HTML文件,它的名字是"attachment.html"。



Content-disposition这持告诉邮件程序假如可能就以内嵌的方式显示附件。现在新的邮件程序会在消息后显示HTML的内容。假如Content-disposition被设为attachment,那么邮件程序就不会显示HTML文件的内容,而是显示一个连接到文件的图标(或其它的类似的东西)。收件人要看附件的内容,必须点击这个图标。一般情况下,假如附件是一些文本(包含HTML),Content-disposition会被设为inline,这是因为现在大部分邮件程序能够不借助其它浏览器而直接显示附件(文本)的内容。假如附件不是文本(比如图片或其它类似的内容),Content-disposition就设为attachment。



2. 用PHP生成带附件的电子邮件
这里一个例子,告诉你假如把一个定义好的HTML文件加为邮件的附件:
<?php
# 我们首先写实际的消息内容
$emailBody = "This is text that goes into the body of the email.";
# 然后我们要作为附件的HTML文件
$attachment = "<html>
<head>
<title>The attached file</title>
</head>
<body>
<h2>This is the attached HTML file</h2>
</body>
</html>";

说明:用PHP实现发送电子邮件是比较简单的!大家可以看看如下完整代码。

1.把下面这段代码复制到你的网页中,可以复制到.HTML文件中。

<form action="mail.php" method="post">
<p align="center">
<font face="Verdana">
Name:<br>
<input type="text" name="name" style="border: 1px solid #000000" style="font: Verdana" style="color: #000000" style="font-size: 8pt" style="background-color: #FFFFFF"><br>
E-Mail Address:<br>
<input type="text" name="email" style="border: 1px solid #000000" style="font: Verdana" style="color: #000000" style="font-size: 8pt" style="background-color: #FFFFFF"><Br>
Website URL:<br>
<input type="text" name="url" style="border: 1px solid #000000" style="font: Verdana" style="color: #000000" style="font-size: 8pt" style="background-color: #FFFFFF"><Br>
<input type="submit" value="Submit" style="border: 1px solid #000000" style="font: Verdana" style="color: #000000" style="font-size: 8pt" style="background-color: #FFFFFF">

2. 建立mail.php文件,并且和上面的保存在同一个目录中。

<?
$contactemail = "you@yourdomain.com";
$subject = "You choose";
$message .= "Name: $namen";
$message .= "E-mail: $emailn";
$message .= "Website URL: $urln";
mail($contactemail, $subject, $message);
echo "Thanks for mailing me, I should reply with in a few
days."
?>

[!--infotagslink--]

相关文章

  • NodeJS实现阿里大鱼短信通知发送

    本文给大家介绍的是nodejs实现使用阿里大鱼短信API发送消息的方法和代码,有需要的小伙伴可以参考下。...2016-01-20
  • PHP测试成功的邮件发送案例

    mail()函数的作用:连接到邮件服务器,利用smtp协议,与该服务器交互并投邮件。注意:1、mail函数不支持esmtp协议,---即,只能直投,不能登陆2、由上条,我们只能直投至最终的收件服务器地址.而该地址,又是在PHP.ini中指定的,所...2015-10-30
  • php邮件发送的两种方式

    这篇文章研究的主要内容就是使用PHP来发送电子邮件,总结为以下两种方法:一、使用PHP内置的mail()函数<&#63;php $to = "test@163.com"; //收件人 $subject = "Test"; //主题 $message = "This is a test mail!"; //正文...2015-10-30
  • c# 实现发送邮件的功能

    这篇文章主要介绍了c# 如何实现发送邮件的功能,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下...2020-07-07
  • php邮件发送的两种方式

    这篇文章研究的主要内容就是使用PHP来发送电子邮件,总结为以下两种方法:一、使用PHP内置的mail()函数<&#63;php $to = "test@163.com"; //收件人 $subject = "Test"; //主题 $message = "This is a test mail!"; //正文...2015-10-30
  • python实现企业微信定时发送文本消息的实例代码

    这篇文章主要介绍了python实现企业微信定时发送文本消息的实例代码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-11-25
  • c#使用netmail方式发送邮件示例

    这篇文章主要介绍了c#使用netmail方式发送邮件的示例,大家参考使用吧...2020-06-25
  • PHP测试成功的邮件发送案例

    mail()函数的作用:连接到邮件服务器,利用smtp协议,与该服务器交互并投邮件。注意:1、mail函数不支持esmtp协议,---即,只能直投,不能登陆2、由上条,我们只能直投至最终的收件服务器地址.而该地址,又是在PHP.ini中指定的,所...2015-10-30
  • PHPMailer在SAE上无法发送邮件的解决方法

    PHPMailer在SAE上无法发送邮件怎么回事呢,我们以前在php5.2.7版本中使用了PHPMailer是可以发,但移到sae中发现无法发邮件了,那么此问题如何解决 在SAE上直接用5.2.7...2016-11-25
  • 整理几个android后台发送邮件的方法

    本文我们整理了三个android后台发送邮件的方法及示例,第一个是不借助Intent在android后台发送Email,第二个是用在收集应用的异常信息,第三个是分享一个android后台发送邮...2016-09-20
  • Perl中使用MIME::Lite发送邮件实例

    这篇文章主要介绍了Perl中使用MIME::Lite发送邮件实例,本文介绍了使用sendmail方式发送、发送HTML格式邮件、smtp方式发送邮件等内容,需要的朋友可以参考下...2020-06-29
  • 网上找到的两个PHP发送邮件的例子,很不错,贴出来给初学者参考吧(不知道是否有兄弟曾贴过),呵呵(2

    Advanced Example Here we will show the full capabilities of the PHP mail function. PHP Code: <?php echo "<html><body>"; $recipient = "Kris Arndt <karn@nu...2016-11-25
  • node.js 基于 STMP 协议和 EWS 协议发送邮件

    这篇文章主要介绍了node.js 基于 STMP 协议和 EWS 协议发送邮件的示例,帮助大家更好的理解和使用node.js,感兴趣的朋友可以了解下...2021-02-15
  • Delphi7中群发Email邮件的方法

    这篇文章主要介绍了Delphi7中群发Email邮件的方法,涉及邮件服务器软件的使用,电子邮件的判断与发送功能的实现,是非常实用的技巧,需要的朋友可以参考下...2020-06-30
  • PHP利用Jmail组件实现发送邮件

    学过asp的朋友可能知道jmail组件是使用在asp中一个常用的邮箱发送功能,在php中如果想调用jmail功能我们需要使用com组件来操作。 我们先来介绍格式 代码如...2016-11-25
  • phpMailer 发送邮件

    //原创:www.111cn.net 注明:转载说明来处www.111cn.net // 昨天听一网友说用php 里面的mail发邮件发不出去,我想一般都是发不了的,现在大多数据邮件提供商都不准那样了...2016-11-25
  • C#编程实现发送邮件的方法(可添加附件)

    这篇文章主要介绍了C#编程实现发送邮件的方法,具备添加附件的功能,涉及C#文件传输及邮件发送的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • php中利用curl smtp发送邮件实例

    本文章来介绍人一下关于与我们不同的发送邮件的方法我们来利用php curl stmp来实现邮件的发送程序。 $ telnet 邮箱SMTP服务地址 25 Trying 邮箱服务IP地址......2016-11-25
  • Python基于httpx模块实现发送请求

    这篇文章主要介绍了Python基于httpx模块实现发送请求,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-07-08
  • php定时发送邮件

    <?php // 请求 PHPmailer类 文件 require_once("class.phpmailer.php"); //发送Email函数 function smtp_mail ( $sendto_email, $subject, $body, $extra_hd...2016-11-25