跟落实步骤。程序下SMTP协议来发送电邮及接收者的邮件服务器。

今天学习了网络客户端编程

可应用Python的email模块来促成带有附件的邮件的殡葬。

重大看了文件传输和电子邮件

SMTP (Simple Mail Transfer Protocol)
邮件传送代理 (Mail Transfer Agent,MTA)
程序使用SMTP协议来发送电邮及接收者的邮件服务器。SMTP协议只能用来发送邮件,不可知用来收取邮件。大多数的邮件发送服务器
(Outgoing Mail Server) 都是行使SMTP协议。SMTP协议的默认TCP端口号是25。

不曾非常细之拘留

SMTP协议的一个最主要特征是其亦可接力传送邮件。它工作以少种植情况下:一凡电子邮件从客户机传输到服务器;二凡是起某个一个服务器传输到其他一个服务器。

道根本还是要是明白其考虑

POP3 (Post Office Protocol) & IMAP (Internet Message Access Protocol)
POP协议和IMAP协议是用来邮件接收的无比广泛的个别栽协议。几乎所有的邮件客户端和服务器都支持即简单种协议。

和落实步骤

POP3商谈也用户提供了同样种植简易、标准的点子来做客邮箱与收获电邮。使用POP3商讨的电邮客户端通常的工作经过是:连接服务器、获取具有信息并保留于用户主机、从服务器删除这些信然后断开连接。POP3商的默认TCP端口号是110。

要为此底时节便不曾那紧了

IMAP协议为提供了便利的邮件下充斥服务,让用户会展开离线阅读。使用IMAP协议的电邮客户端通常将信息保存在服务器上直到用户显式删除。这种特征使得多只客户端可又管理一个信箱。IMAP协议提供了摘要浏览功能,可以吃用户在阅读了所有的邮件至时刻、主题、发件人、大小相当于消息后再也决定是否下载。IMAP协议的默认TCP端口号是143。

4.1首先:什么是因特网客户端
  因特网客户端到底是呀”?要回应是问题,我们把因特网简化成一个数码交换中心,数据交换的参与者是一个服务提供者和一个劳务的使用者。有的人拿它们称作“生产者-消费者”(虽然这个词一般只所以当授课操作系统相关信息时)。服务器即是劳动者,它提供劳动,一般才出一个服务器(进程或主机等),和多单买主,就比如咱事先看之客户端/服务器模型那样。虽然现在咱们不再采取的级别之套接字来创造因特网客户端,但范是完全相同的。
  

邮件格式 (RFC 2822)
诸封邮件都来有限个组成部分:邮件头和邮件体,两者采用一个空行分隔。

4.2.1文件传输
  因特网中最盛行的事务就是是文本之交换。文件交换无处不在。有无数商事得以供因特网上传文件使用。最流行的来文件传输协议(FTP),Unix-to-Unix
复制协议(UUCP),以及网页的超文本传输协议(HTTP)。另外,还有(Unix
下之)远程文件复制指令rcp(以及再安全,更活的scp 和rsync)。

邮件头每个字段 (Field)
包括个别片段:字段名和字段值,两者采用冒号分隔。有零星单字段需要注意:From和Sender字段。From字段指明的是邮件的撰稿人,Sender字段指明的凡邮件的发送者。如果From字段包含多于一个的撰稿人,必须指定Sender字段;如果From字段只生一个作者以作者及发送者相同,那么不应更下Sender字段,否则From字段和Sender字段应该以以。

4.2.2文件传输协议(FTP)
  它根本用于匿名下载公共文件。也堪用于在简单高电脑里传输文件,尤其是于行使Unix
系统召开吗文件存储系统,使用其它机器来干活之状。早以网流行之前,FTP
就是于因特网上文件传输,软件与源代码下载的要手段有。FTP
要求输入用户称以及密码才能够访问远程的FTP
服务器,但她吧同意尚未帐号的用户以匿名用户登录。不过,管理员要优先安装FTP
服务器允许匿名用户登录。这时,匿名用户的用户名“anonymous”,密码一般是用户的e-mail
地址。与特定的用户拥有一定的帐户不同,这起硌像是把FTP
公开出来让大家看。匿名用户通过FTP
协议可以下的指令和一般的用户比来说,限制更多。

邮件体包含邮件的情,它的种类由邮件头之Content-Type字段指明。RFC
2822概念之邮件格式中,邮件体只是才的ASCII编码的字符序列。

其工作流程如下:
  1. 客户端连接远程的FTP 服务器
  2. 客户端输入用户称与密码(或“anonymous”和e-mail 地址)
  3. 客户端做各种文件传输和消息查询操作
  4. 客户端上出远程FTP 服务器,结束通讯

MIME (Multipurpose Internet Mail Extensions) (RFC 1341)
MIME扩展邮件的格式,用以支持非ASCII编码的文书、非文本附件和带有多独片
(multi-part) 的邮件体等。

  当然,这只是是好泛的一个流水线。有时,由于网络有限边电脑的垮台或是网络的问题,会招致整工作在得之前为搁浅。一般,在客户端超过15
分钟(900 秒)不移步过后,连接就见面被关闭。在底部上,FTP
只利用TCP(见前面网络编程相关章节)——它不动UDP。而且,FTP
是客户端/服务器编程中十分“与众不同”的例证。客户端以及服务器都运简单独拟接字来报道:一个凡是决定以及指令端口(21
号端口),另一个是数码端口(有时是20
哀号端口)。客户端和服务器使用指令与控制端口发送FTP
协议,而数经过数据端口传输。我们说“有时”是为FTP
有点儿种植模式:主动与消沉。只有当主动模式服务器才以数据端口。在服务器将20
如泣如诉端口设置也数量端口后,它“主动”连接客户端的数端口。而被动模式中,服务器只是告诉客户端它的轻易端口的数码,客户端必须主动建立数量连接。在这种模式下,你见面看到,FTP
服务器在成立数量连接时凡“被动”的。最后,现在既来了相同种植扩大被动模式来支持第6
版本的因特网协议(IPv6)地址——见 RFC 2428。

Python email模块

 

  1. class email.message.Message

Python 已经支撑了概括FTP
在内的几近数量因特网协议。支持各个协议的客户端模块可以http://docs.python.org/lib/internet.html
找到。现在看用Python 创建一个因特网客户端程序有多简单。

__getitem__,__setitem__实现obj[key]款式之造访。
Msg.attach(playload): 向当前Msg添加playload。
Msg.set_playload(playload): 把一切Msg对象的邮件体设成playload。
Msg.add_header(_name, _value, **_params): 添加邮件头字段。

4.3.1python和FTP

  1. class email.mime.base.MIMEBase(_maintype, _subtype, **_params)
    具备MIME类的基类,是email.message.Message类的子类。

  2. class email.mime.multipart.MIMEMultipart()

那么,我们怎么用Python 写FTP
客户端程序呢?其实,我们前曾经涉嫌过部分了。现在还要更长相应的Python
模块导入和调用的操作。现在再来回顾一下流程:

当3.0本子的email模块 (Python 2.3-Python 2.5)
中,这个类位于email.MIMEMultipart.MIMEMultipart。
其一看似是MIMEBase的一直子类,用来深成包含多只有的邮件体的MIME对象。

  1. 总是到服务器
  2. 登录
  3. 产生劳动要求 (有或有归信息)
  4. 退出
  1. class email.mime.text.MIMEText(_text)

以应用Python 的FTP 支持时,你所需要举行的饶是导入ftplib
模块,并实例化一个ftplib.FTP类对象。所有的FTP
操作(如登录,传输文件以及刊登等)都如动用这个目标来形成。下面是同段Python的伪代码:

利用字符串_text来生成MIME对象的中心文本。

from ftplib import FTP
f = FTP(‘ftp.python.org’)
f.login(‘anonymous’, ‘guess@who.org’)
:
f.quit()
以羁押真正的事例之前,我们而优先熟悉一下ftplib.FTP
类的法门,这些方法将在代码中之所以到。

代码实现

 

复制代码 代码如下:

4.3.2ftplib.FTP类方法
  也就是说,你不自然要是动用其它的措施,因为她或是扶持函数,或者是管理函数,或者是受API
调用的。

!/usr/bin/env python
# -*- coding: UTF-8 -*-

表17.1 FTP 对象的方法
方法             描述
login(user=’anonymous’,
passwd=”, acct=”)      登录到FTP 服务器,所有的参数都是可选的
pwd()             得到当前工作目录
cwd(path)           把当前工作目录设置也path
dir([path[,…[,cb]])       显示path
目录里之情节,可摘的参数cb 是一个回调函数,它会为污染给retrlines()方法
nlst([path[,…])
与dir()    类似,但回来一个文书称之列表,而休是显示这些文件称
retrlines(cmd [, cb])       给定FTP 命令(如“RETR
filename”),用于下载文件文件。可摘的回调函数cb 用于拍卖文件的各国一行
retrbinary(cmd, cb[,
bs=8192[,
ra]])        与retrlines()类似,只是这令处理二进制文件。回调函数cb
用于拍卖各一样片(块好小默认为8K)下载的数目。
storlines(cmd, f)        给定FTP 命令(如“STOR
filename”),以上传文本文件。要于一定一个文本对象f
storbinary(cmd, f[,
bs=8192])
          与storlines()类似,只是这令处理二进制文件。要让一定一个文件对象f,上传块大小bs
默认为8Kbs=8192])
rename(old, new)         把远程文件old 改名为new
delete(path)       删除位于path 的远距离文件
mkd(directory)       创建远程目录
rmd(directory)         删除远程目录
quit()         关闭连接并退出

from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email.mime.text import MIMEText

以形似的FTP 通讯中,要运及之命发出login(), cwd(), dir(), pwd(),
stor*(), retr*()和quit()。有一部分从未有过排有的FTP
对象方法也是雅有因此底。请参考Python 的文档以抱更多关于FTP 对象的音讯:

# python 2.3.*: email.Utils email.Encoders
from email.utils import COMMASPACE,formatdate
from email import encoders

http://python.org/docs/current/lib/ftp-objects.html

import os

4.3.3客户端FTP程序举例

#server[‘name’], server[‘user’], server[‘passwd’]
def send_mail(server, fro, to, subject, text, files=[]):
    assert type(server) == dict
    assert type(to) == list
    assert type(files) == list

  之前我们说罢,你可以不写剧本,在互动环境面临动用FTP。不过,下面我们要要写一截脚本,假要你如果自Mozilla
的网站下载最新的Bugzilla 的代码。例17.1
就是用来成功这工作之。我们在尝试着写一个应用程序,不过,你也可交互式地运作就段代码。我们的程序下FTP
库来下充斥文件,也做了片破绽百出检测。不过,程序并无全自行。你要是团结控制什么时候如果去下载。如果您以动用类Unix
系统,你可以设定一个“cron”任务来机关下载。另一个题目是,如果文件的文本称或目录名改了吧,程序就算未克正常办事了。

    msg = MIMEMultipart()
    msg[‘From’] = fro
    msg[‘Subject’] = subject
    msg[‘To’] = COMMASPACE.join(to) #COMMASPACE==’, ‘
    msg[‘Date’] = formatdate(localtime=True)
    msg.attach(MIMEText(text))

规章17.1 FTP 下载示例 (getLatestFTP.py)
此程序用于下载网站中风行版本的文书。你得修改是次为其下充斥而嗜的先后。

    for file in files:
        part = MIMEBase(‘application’, ‘octet-stream’) #’octet-stream’:
binary data
        part.set_payload(open(file, ‘rb’.read()))
        encoders.encode_base64(part)
        part.add_header(‘Content-Disposition’, ‘attachment;
filename=”%s”‘ % os.path.basename(file))
        msg.attach(part)

1 #!/usr/bin/env python
2
3 import ftplib
4 import os
5 import socket
6
7 HOST = 'ftp.mozilla.org'
8 DIRN = 'pub/mozilla.org/webtools'
9 FILE = 'bugzilla-LATEST.tar.gz'
10
11 def main():
12 try:
13 f = ftplib.FTP(HOST)
14 except (socket.error, socket.gaierror), e:
15 print 'ERROR: cannot reach "%s"' % HOST
16 return
17 print '*** Connected to host "%s"' % HOST
18
19 try:
20 f.login()
21 except ftplib.error_perm:
22 print 'ERROR: cannot login anonymously’
23 f.quit()
24 return
25 print '*** Logged in as "anonymous"'
26
27 try:
28 f.cwd(DIRN)
29 except ftplib.error_perm:
30 print 'ERROR: cannot CD to "%s"' % DIRN
31 f.quit()
32 return
33 print '*** Changed to "%s" folder' % DIRN
34
35 try:
36 f.retrbinary('RETR %s' % FILE,
37 open(FILE, 'wb').write)
38 except ftplib.error_perm:
39 print 'ERROR: cannot read file "%s"' % FILE
40 os.unlink(FILE)
41 else:
42 print '*** Downloaded "%s" to CWD' % FILE
43 f.quit()
44 return
45
46 if __name__ == '__main__':
47 main()

    import smtplib
    smtp = smtplib.SMTP(server[‘name’])
    smtp.login(server[‘user’], server[‘passwd’])
    smtp.sendmail(fro, to, msg.as_string())
    smtp.close()

 

动用python的smtplib库实现邮件发送

假定运行脚本时从没错,则会获得如下输出:

复制代码 代码如下:

$ getLatestFTP.py
*** Connected to host "ftp.mozilla.org"
*** Logged in as "anonymous"
*** Changed to "pub/mozilla.org/webtools" folder
*** Downloaded "bugzilla-LATEST.tar.gz" to CWD
$

import smtplib
def sendmail():
    try:
        smtp=smtplib.SMTP(HOST)
        smtp.login(USER,PASSWORD)     #报到邮箱
        smtp.sendmail(USER+”@”+PROFIX,TO,MSG)  #出殡邮件
        smtp.quit()
        print ’email send success’
    except Exception,e:
        print e
        print ’email send failed.’

 

邮件可以发送了

逐行解释
1-9 行
  代码前几行导入要就此之模块和安装有些常量
11-44 行
  main()函数分为以下几步:创建一个FTP 对象,尝试连接到FTP
服务器(12-17
行)然后回。在来外不当有的上离。我们品尝用“anonymous”登录,如果坏就终止(19-25
行)。下同样步就是是改变至公布目录(27-33 行),最后,下载文件(35-44 行)。

下一场上了好几概念msg
python中产生几乎个类库生成长的msg格式
总结一个简单的MIMEText,可以编制许多邮件头信息,也足以编写邮件格式
from email.MIMEText import MIMEText
msg=MIMEText(“要发送的内容”,”格式,例如:html,plain”,”编码,例如:gb2312,utf-8″)
msg[‘From’]=’邮件中显的发送方的名’
msg[‘To’]=’邮件被形收件方的讳’
msg[‘Subject’]=’邮件标题’
这些都好无设置

  于35-36
行,我们污染了一个回调函数给retrbinary(),它当各个接收到一块二进制数据的时光都见面为调用。这个函数就是咱们创建的当地文件对应文件对象的write
方法。在传截止的下,Python解释器会自动关闭是文件对象,而不见面丢掉数据。虽然这样好,但极致好或不要这么做,做吧一个程序员,要尽量做到以资源不再叫采用的当儿即便直接出狱,而不是因其它代码来举行释放操作。在这里,
我们应有将公文对象保存至一个变量中, 如变量loc , 然后拿loc.write
传为ftp.retrbinary()方法。
当代码中,如果由于一些原因我们无能为力保存之文件,那要管有的空文件给删掉,以防搞乱文件系统(40
行)。最后,我们下了try-except-else 子句(35-42
行),而无是描摹点儿整整关闭FTP连接然后返回的代码。

http://www.bkjia.com/Pythonjc/618197.htmlwww.bkjia.comtruehttp://www.bkjia.com/Pythonjc/618197.htmlTechArticle可以使用Python的email模块来实现带有附件的邮件的发送。
SMTP (Simple Mail Transfer Protocol) 邮件传送代理 (Mail Transfer
Agent,MTA) 程序使用SMTP协议来…

46-47 行
  这是运行独立脚本的惯用方法。

4.4.1电子邮件

  于看e-mail 的底层的构造之前,你生出无发问过好,e-mail
的相当定义到底是啊?根据RFC2822,“消息由头域(合起来给消息头)以及背后可摘的消息体组成”。对于一般用户来说,一说从e-mail
就会为咱们想到它的内容,不管它是同等封闭真的邮件或一样封不请自来的商业广告(即spam,垃圾邮件),都应生出情。不过,RFC
规定,邮件体是可选的,只有邮件头是不可或缺的。这无异于沾使特别注意。

4.4.2E-mail 系统组件和情商

  不管您是哪些想的,电子邮件(e-mail)实际上以现世的因特网出现之前就是早已冒出了。它同样开始用于mainframe
的用户中简单的交换信息。注意,由于她们都以应用同样台电脑,所以,这里还都没提到到网络。后来,当网络成为实际的上,用户就得以不同的主机里交换信息。当然,由于用户用正在不同之处理器,电脑内利用在不同之磋商,信息置换成了一个可怜复杂的定义。直到20
世纪80 年代,因特网上之所以e-mail
进行信息交换才发出了一个其实的汇合之正统。在深刻细节之前,我们先问问自己,e-mail
是怎么工作之?一久消息是什么从发件人那么通过广大的因特网,到达收件人之?简单点以来,有平等高发送电脑(发件人之信息于此间发送出),和同光目的电脑(收件人之信件服务器)。最好的解决方案是发送电脑知道哪连接至接电脑,这样一来,它便足以一直把消息发送过去。不过,实际上一般并无这样顺利。发送电脑要询问及某一样大中等主机,这令中等主机能抵达最终之收件主机。然后就尊中等主机要物色一宝离目的主机更近乎一些的主机。所以,在殡葬主机与目的主机里,可能会见产生差不多雅名为“跳板”的主机。如果您精心瞧您收到的e-mail
的邮件头,你会看出一个“passport”标记,其中记录了邮件寄于你马上一头达到且交了了哪些地方。为了为叙清楚部分,让我们先瞧e-mail
系统的逐条零部件。最重点的机件是信息传代理(MTA)。这是一个在邮件交换主机上运行的一个服务器程序,它当邮件的路由,队列和殡葬工作。
  它们就是是邮件从源主机及目的主机所而通过的跳板。所以也深受叫作是“信息传输”的“代理”。要给具备这些工作起,MTA
要掌握少项事情:1) 如何找到消息应去之下一台MTA 2) 如何与其他一样令MTA
通讯。第一起事由域名服务(DNS)来搜寻目的域名的MX(邮件交换Mail
eXchange)来形成。这对最后之收件人是休必要的,但针对其他的跳板来说,则是必需的。对于第二起事,MTA怎么把消息转给其他的MTA
呢?

4.4.3发送E-mail

  要能发送e-mail,你的邮件客户端一定要是连接至一个MTA,它们凭借某种协议进行报道。MTA
之间通讯所动的磋商被消息传体系(MTS)。只有简单独MTA
都采取是协议时,才会进行报道。在本节起经常即便说了,由于原先在重重不一的电脑体系,每个系统都采用不同之网络软件,这种通讯很危险,具有不可预知性。更扑朔迷离的是,有的电脑使用互连的纱,而部分电脑使用调制解调器拨号,消息之殡葬时间吧是不足预知的。事实上,笔者就有相同查封邮件在殡葬9
独月后才接过!互连网的速度怎么会这样慢?出于对这些复杂度的考虑,现代e-mail
的根基之一,简单邮件传输协议(SMTP)于1982 年出现了。

SMTP
  SMTP 由死的Jonathan
Postel(加利福尼亚大学信息学院)创建,记录在RFC 821 中,于1982 年8
月颁布。其后底改记录在RFC 2821 中,于2001 年4
月宣告。一些已实现了SMTP的资深MTA 包括:

开源MTA
􀁺 Sendmail
􀁺 Postfix
􀁺 Exim
z qmail (免费发布,但未开源)
商业MTA
􀁺 Microsoft Exchange
􀁺 Lotus Notes Domino Mail Server

小心,虽然其还实现了RFC 2821 中定义之极端小化SMTP
协议,它们遭的大多数,尤其是有些买卖MTA,都当服务器中入了商谈定义之外的特有的效果。SMTP
是在因特网上MTA 之间用于信息交换的最好常用的MTS。它给MTA 用来拿e-mail
从平尊主机传送到任何一样雅主机。在公发e-mail
的时光,你必须要连接到一个外表的SMTP
服务器,这时,你的邮件程序是一个SMTP 客户端。你的SMTP
服务器也就此成为了卿的信的率先独跳板。 

 

4.5.1Python和SMTP
然,也存在一个smtplib 模块和一个smtplib.SMTP
类要实例化。再来探视是早已熟悉的了
程吧:

  1. 连接至服务器
  2. 报到(如果需要的话)
  3. 发劳动请
  4. 退出
    譬如说NNTP 一样,登录是可选的,只有以服务器打开了SMTP
    认证(SMTP-AUTH)时才要登录。SMTP-AUTH
    以RFC 2554 中定义。还是跟NNTP 一样,SMTP 通讯时,只要一个端口25。
    下面是一对Python 的伪代码:
    from smtplib import SMTP
    n = SMTP(‘smtp.yourdomain.com’)

    n.quit()
    当羁押真的例子之前,我们而优先介绍一下smtplib.SMTP 类的片常用的方法。

4.5.2smtplib.SMTP 类方法
  跟之前一样,我们会列有smtplib.SMTP
类的章程,但非见面列有具有的方,只排有而创造SMTP客户端程序所用之道。对大多数e-mail
发送程序来说,只发生半点单方法是须的:sendmail()和it()。    sendmail()的有所参数都使遵循RFC
2822,即e-mail
地址必须要发不利的格式,消息体要发生不易的前导头,前导头后面是个别个回车和换行(\r\n)对。注意,实际的消息体不是不可或缺的。根据RFC
2822,“唯一要求的腔信息只有发送日期及殡葬地址”,即“Date:”和“From:”:(MAIL
FROM, RCPT TO,
DATA)还有局部计无于提到,不过,一般的话,它们不是发送e-mail
所不可不的。请参考Python文档以博得SMTP 对象的有办法的音讯。

说明17.3 SMTP 对象的办法
方法         描述
Sendmail(from, to, msg[,mopts, ropts])           把msg
从from 发送给to(列表或元组)。ESMTP
设置(mopts)和收件人设置(ropts)为可选。
quit()
                          关闭连接,然后退出
login(user, passwd)a                     使用user
用户和passwd 密码登录到SMTP 服务器a. 只于生SMTP-AUTH 时采取。

4.4.5 交互式SMTP 示例***
  同地,我们先被一个交互式的例子:


>>> from smtplib import SMTP as smtp
>>> s = smtp('smtp.python.is.cool')
>>> s.set_debuglevel(1)
>>> s.sendmail('wesley@python.is.cool', ('wesley@python.is.cool',
'chun@python.is.cool'), ''' From: wesley@python.is.cool\r\nTo:
wesley@python.is.cool, chun@python.is.cool\r\nSubject: test
msg\r\n\r\nxxx\r\n.''')
send: 'ehlo myMac.local\r\n'
reply: '250-python.is.cool\r\n'
reply: '250-7BIT\r\n'
reply: '250-8BITMIME\r\n'
reply: '250-AUTH CRAM-MD5 LOGIN PLAIN\r\n'
reply: '250-DSN\r\n'
reply: '250-EXPN\r\n'

reply: '250-HELP\r\n'
reply: '250-NOOP\r\n'
reply: '250-PIPELINING\r\n'
reply: '250-SIZE 15728640\r\n'
reply: '250-STARTTLS\r\n'
reply: '250-VERS V05.00c++\r\n'
reply: '250 XMVP 2\r\n'
reply: retcode (250); Msg: python.is.cool
7BIT
8BITMIME
AUTH CRAM-MD5 LOGIN PLAIN
DSN
EXPN
HELP
NOOP
PIPELINING
SIZE 15728640
STARTTLS
VERS V05.00c++
XMVP 2
send: 'mail FROM:<wesley@python.is.cool> size=108\r\n'
reply: '250 ok\r\n'
reply: retcode (250); Msg: ok
send: 'rcpt TO:<wesley@python.is.cool>\r\n'
reply: '250 ok\r\n'
reply: retcode (250); Msg: ok
send: 'data\r\n'
reply: '354 ok\r\n'
reply: retcode (354); Msg: ok
data: (354, 'ok')
send: 'From: wesley@python.is.cool\r\nTo:
wesley@python.is.cool\r\nSubject: test
msg\r\n\r\nxxx\r\n..\r\n.\r\n'
reply: '250 ok ; id=2005122623583701300or7hhe\r\n'
reply: retcode (250); Msg: ok ; id=2005122623583701300or7hhe
data: (250, 'ok ; id=2005122623583701300or7hhe')
{}
>>> s.quit()
send: 'quit\r\n'
reply: '221 python.is.cool\r\n'
reply: retcode (221); Msg: python.is.cool

 

 

相关文章