PHP用socket连接SMTP服务器发送邮件

PHP用socket连接SMTP服务器发送邮件学习实验记录:

分析与SMTP会话的一般流程

1. HELO XXX \r\n //XXX就是自己起个名字,和服务器打个招呼

返回 250 表示成功

2. AUTH LOGIN \r\n //请求与服务器开始验证用户(登陆)

返回 334 表示成功

3. 用户名 \r\n //直接发送用户名PHP中将用户名base64_encode()下

返回 334 表示成功

4. 密码 \r\n //直接发送密码PHP中将密码base64_encode()下

返回235表示成功

5. MAIL FROM \r\n //发件人邮箱地址,一般和上面的用户名密码对应的油箱

返回 250 表示成功

6. RCPT TO \r\n //收件人地址

返回 250 表示成功

7. DATA \r\n //告诉服务器下面开始传输邮件

返回 354 表示成功

8. 传输邮件数据:可以发送邮件了,格式为

From:回信人地址 \r\n //貌似可以写别人的,嘿嘿

Subject:邮件标题 \r\n

To:收件人地址 \r\n

\r\n

正文数据 \r\n

以这个格式发送至服务器,返回250表示发送成功

9. QUIT \r\n 断开连接

返回 221 表示成功

PHP实验程序如下:

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>mail</title>

</head>

<body>

<?php

//以QQ邮箱为例子,要先开通SMTP/POP3功能

$smtp="smtp.qq.com";   //SMTP邮件发送服务器

$title="标题";     //邮件标题

$username="qq邮箱帐户";   //SMTP用户名

$passwd="邮箱密码";   //SMTP密码

$mailfrom="qq邮箱帐户下的地址,也就是自己的QQqq邮箱地址,不能填别人的"; //发送人

$mailfrom1="别人点回复邮件将回复到此回复邮箱中,可以填写别人的";        //回复邮件人

$rcptto="收件箱地址"; //收件人

$mail="邮件内容";     //邮件正文

 

smail($smtp,$title,$username,$passwd,$mailfrom,$mailfrom1,$rcptto,$mail);

 

function smail($smtp,$title,$username,$passwd,$mailfrom,$mailfrom1,$rcptto,$mail){

$message="";

$message .= "正在连接服务器...<br>";

$link = fsockopen($smtp,25);

if ($link){

 set_socket_blocking($link,true);

 $lastmessage=fgets($link,512);

 

 if (!ereg("^220",$lastmessage)){

  $message .= "与服务器连接失败" . $lastmessage . "<br>";

 }

 else{

  $message .= "与服务器连接成功,服务器就绪:" . $lastmessage . "<br>";

 

  fputs($link,"HELO phpsetmail"."\r\n");

  $lastmessage=fgets($link,2000);

  if (ereg("^250",$lastmessage)){

   $message .= "与服务器HELO成功:" .$lastmessage. "<br>";

  }

  else{

   $message .= "与服务器HELO失败:" .$lastmessage. "<br>";

  }

 

  fputs($link,"AUTH LOGIN"."\r\n");

  $lastmessage=fgets($link,2000);

  if (ereg("^334",$lastmessage)){

   $message .= "请求与服务器进行用户验证成功:" .$lastmessage. "<br>";

  }

  else{

   $message .= "请求与服务器进行用户验证失败:" .$lastmessage. "<br>";

  }

 

  fputs($link,base64_encode($username)."\r\n");

  $lastmessage=fgets($link,2000);

  if (ereg("^334",$lastmessage)){

   $message .= "与服务器用户验证成功:" .$lastmessage. "<br>";

  }

  else{

   $message .= "与服务器用户验证失败:" .$lastmessage. "<br>";

  }

 

  fputs($link,base64_encode($passwd)."\r\n");

  $lastmessage=fgets($link,2000);

  if (ereg("^235",$lastmessage)){

   $message .= "与服务器密码验证成功:" .$lastmessage. "<br>";

  }

  else{

   $message .= "与服务器密码验证失败:" .$lastmessage. "<br>";

  }

 

  fputs($link,"MAIL FROM:$mailfrom"."\r\n");

  $lastmessage=fgets($link,2000);

  if (ereg("^250",$lastmessage)){

   $message .= "与服务器MAIL FROM成功:" .$lastmessage. "<br>";

  }

  else{

   $message .= "与服务器MAIL FROM失败:" .$lastmessage. "<br>";

  }

 

  fputs($link,"RCPT TO:$rcptto"."\r\n");

  $lastmessage=fgets($link,2000);

  if (ereg("^250",$lastmessage)){

   $message .= "与服务器RCPT TO成功:" .$lastmessage. "<br>";

  }

  else{

   $message .= "与服务器RCPT TO失败:" .$lastmessage. "<br>";

  }

 

  fputs($link,"DATA"."\r\n");

  $lastmessage=fgets($link,2000);

  if (ereg("^354",$lastmessage)){

   $message .= "请求与服务器发送邮件数据成功:" .$lastmessage. "<br>";

   fputs($link,"From:$mailfrom1" . "\r\n");

   fputs($link,"Subject:$title" . "\r\n");

   fputs($link,"To:$rcptto" . "\r\n");

   fputs($link,"\r\n");

   fputs($link,$mail . "\r\n");

   fputs($link,"." . "\r\n");

   $lastmessage=fgets($link,2000);

   if (ereg("^250",$lastmessage)){

    $message .= "发送邮件数据成功:" .$lastmessage. "<br>";

   }

   else{

    $message .= "发送邮件数据失败:" .$lastmessage. "<br>";

   }

 

  }

  else{

   echo "请求与服务器发送邮件数据成功:" .$lastmessage. "<br>";

  }

 

  fputs($link,"QUIT"."\r\n");

  $lastmessage=fgets($link,2000);

  if (ereg("^221",$lastmessage)){

   $message .= "与服务器断开连接成功:" .$lastmessage. "<br>";

  }

  else{

   $message .= "与服务器断开连接失败:" .$lastmessage. "<br>";

  }

 

 }

 echo "s_".$message;

}

else{

 echo "err_";

}

fclose($link);

}

?>

</body>

</html>

例子成功返回如下

s_正在连接服务器...

与服务器连接成功,服务器就绪:220 Esmtp QQ Mail Server

与服务器HELO成功:250 Esmtp OK

请求与服务器进行用户验证成功:334 XXXXXXXXX

与服务器用户验证成功:334 XXXXXXXX

与服务器密码验证成功:235 Authentication successful

与服务器MAIL FROM成功:250 Ok

与服务器RCPT TO成功:250 Ok

请求与服务器发送邮件数据成功:354 End data with .

发送邮件数据成功:250 Ok: queued as

与服务器断开连接成功:221 Bye

附:SMTP基本命令集:

命令       描述

——————————

HELO      向服务器标识用户身份发送者能欺骗,说谎,但一般情况下服务器都能检测到。

MAIL      初始化邮件传输

          mail form :

RCPT      标识单个的邮件接收人;常在MAIL命令后面  可有多个rcpt to:

DATA      在单个或多个RCPT命令后,表示所有的邮件接收人已标识,并初始化数据传输结束。

VRFY      用于验证指定的用户/邮箱是否存在;由于安全方面的原因,服务器常禁止此命令

EXPN      验证给定的邮箱列表是否存在,扩充邮箱列表,也常被禁用

HELP      查询服务器支持什么命令

NOOP      无操作,服务器应响应OK

QUIT      结束会话

RSET      重置会话,当前传输被取消

——————————

PHP用socket连接SMTP服务器发送邮件的更多相关文章

  1. Linux 上使用 Gmail SMTP 服务器发送邮件通知

    导读 假定你想配置一个 Linux 应用,用于从你的服务器或桌面客户端发送邮件信息.邮件信息可能是邮件简报.状态更新(如 Cachet).监控警报(如 Monit).磁盘时间(如 RAID mdadm ...

  2. 微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件

    原文:微软BI 之SSIS 系列 - 使用 Script Task 访问非 Windows 验证下的 SMTP 服务器发送邮件 开篇介绍 大多数情况下我们的 SSIS 包都会配置在 SQL Agent ...

  3. JavaMail SMTP服务器发送邮件程序示例 java通过dns服务器解析ip地址

    /** * JavaMail SMTP服务器发送邮件程序示例 * 扮演SMTP服务器角色与邮件客户端软件最大的区别就是: * SMTP服务器需要解析不同接收人邮件地址主机名对应的SMTP服务器主机名 ...

  4. Ubuntu 使用 heirloom-mail 调用外部邮箱 SMTP 服务器发送邮件

    使用本地服务发邮件,经常被过滤掉而且占用资源,发送成功率不高.所以使用外部SMTP服务器发送邮件成为了需求. SMTP认证的目的是为了使用户避免受到垃圾邮件的侵扰,简单地说就是要求必须在提供了账户名和 ...

  5. CentOS7配置mailx使用外部smtp服务器发送邮件

    转自huskiesir的博客: 发送邮件的两种方式: 1.连接现成的smtp服务器去发送(此方法比较简单,直接利用现有的smtp服务器比如qq.新浪.网易等邮箱,只需要直接配置mail.rc文件即可实 ...

  6. centeros 7配置mailx使用外部smtp服务器发送邮件

    发送邮件的两种方式: 1.连接现成的smtp服务器去发送(此方法比较简单,直接利用现有的smtp服务器比如qq.新浪.网易等邮箱,只需要直接配置mail.rc文件即可实现) 2.自己搭建私有的smtp ...

  7. C#利用SMTP服务器发送邮件

    使用.net(C#)发送邮件学习手册(带成功案例) 1.了解发送邮件的三种方式 2.实例介绍使用client.DeliveryMethod = System.Net.Mail.SmtpDelivery ...

  8. [教程] Windows Server 2008 R2架设SMTP服务器发送邮件教程

    Windows Server 2008 R2 架设SMTP服务器实现邮件发送 目的:架设SMTP服务器实现邮件发送. 一.域名设置 添加“邮件交换记录(MX)”: Newjs.cn           ...

  9. Java通过socket实现smtp协议发送邮件

    import java.io.BufferedReader;import java.io.DataOutputStream;import java.io.IOException;import java ...

随机推荐

  1. 123.static静态函数和函数模板

    #include <iostream> using namespace std; //static成员,每个类型都会实例化,创建一个变量,类型一致则共享,否则不共享 template &l ...

  2. android学习笔记五。2、其他组件

    一.ContentProvider内容提供者.是是android中一个应用向第三方共享数据的方式,android中的联系人,sms(短信记录)等都是通过这一方式来向外提供的 1.使用: 在应用中使用C ...

  3. Server.UrlEncode与HttpUtility.UrlEncode的区别

    一.HttpUtility.UrlEncode 方法 1.public static string UrlEncode(byte[]) 将字节数组转换为已编码的 URL 字符串. 2.public s ...

  4. Fedora27 安装Adobe Flash Player PPAPI与NPAPI实现Firefox和Chromium视频播放

    一.Adobe Flash Player PPAPI与NPAPI有什么区别我们在打开网页视频时有时会弹出没有安装Flash插件的提示,此时就无法观看视频.Adobe Flash Player是浏览器显 ...

  5. 【Henu ACM Round #13 C】 Ebony and Ivory

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 先求出c-bx的所有可能 ->存在map里面 然后枚举y看看ay在不在map里面 在的话就有解. 这样复杂度是\(O(N*lo ...

  6. CSUOJ 1549 Navigition Problem

    1549: Navigition Problem Time Limit: 1 Sec  Memory Limit: 256 MBSubmit: 65  Solved: 12 Description N ...

  7. redis练习手册<二>快速入门

    Redis是一个开源,先进的key-value存储,并用于构建高性能,可扩展的Web应用程序的完美解决方案. Redis从它的许多竞争继承来的三个主要特点: Redis数据库完全在内存中,使用磁盘仅用 ...

  8. Introducing ASLR for FreeBSD

    Shawn WebbOliver Pinter10 July 2014http://www.hardenedbsd.org/ [ 1. Introduction ]Security in FreeBS ...

  9. 将yyyyMMdd格式的字符串转成日期DateTime格式

    1.DateTime dt= DateTime.ParseExact("20110720", "yyyyMMdd", Thread.CurrentThread. ...

  10. 从Java到C++——常量的使用规则

    常量是一种标识符,它的值在执行期间恒定不变.C语言用 #define来定义常量(称为宏常量). C++ 语言除了 #define外还能够用const来定义常量(称为const常量). 一.为什么须要常 ...