新浦京81707con > 功能介绍 > 谈谈字符编码,使用TNMSMTP控件在需认证服务器上

原标题:谈谈字符编码,使用TNMSMTP控件在需认证服务器上

浏览次数:194 时间:2019-11-13

前言:

自然那风度翩翩篇是讲关于XML字符编码的,我觉着写着写着看似与XML的关系十分的小了,就改了标题
。所以,看的时候如果感到到摸不到头脑,那就对了,假若以为和你的认知不均等,招待批
评指正。

  今后数不清STMP服务器在发送邮件时均需重新认证叁回,而Delphi的TNMSMTP控件对它从不很“可视化”的支持,使广大人在付出进程中山大学打问号。

 

此处还应该有三个字符编码的主题素材。字符编码在Delphi7中曾经获取了十分的大加强。
Delphi7本人的IDE即便不能够读取Unicode编码的源代码文件,但编译器已经支撑
AnsiString和WideString的改换。相当于说,只要定义的时候定义WideString,
那就是说在末端一向给她赋值时,AnsiString自动转换为WideString,反之亦然。
与此相类似有裨益也可以有缺陷,好处是在便捷支付中,无需考虑越多的字符调换难点,
能够相比较顺手地从Win98向NT字符集调换,坏处是歪曲了字符界限,深入看下
去,一时候搞不清笔者的内部存款和储蓄器里毕竟是Ansi如故Wide,特别是愿意仅仅使用宽字
符的事态下,更要小心字符格式的概念。

  由于如今在做《CSDN查询助手》的时候,使用的也是需认证的服务器(163.com卡塔 尔(英语:State of Qatar)。从其余地方选择了风华正茂部分代码能够化解,将来此发表与大家共享。

无论Outlook XP如故Foxmail,都只可以在HTML格式的电子邮件中放到JPG、GIF格式图片,而音色俱佳的Flash动漫却只得充任电子邮件附属类小零部件发送给好朋友,你可曾认为缺憾?
  使用Delphi完结将Flash动漫(.SWF格式卡塔 尔(英语:State of Qatar)嵌入到电子邮件正文中发送的职能,Foxmail、Outlook均能够依据HTML格式的邮件查看,何况263、163等免费电子邮件还帮助Web分界面直接浏览。缺憾的是,Sina、Sohu无需付费电子邮件的Web分界面则不援助,只好将Flash动漫作为附属类小零部件提供。
风华正茂、程序原理
  下面前蒙受本程序相关的第风流洒脱理论知识做些解释,援助我们知晓本程序的规律。越多的内容,限于文章篇幅,请参见相关的仿效书、帮衬文件。
1.TNMSMTP控件
  电子邮件发送进度都必得遵从SMTP左券。顾客端和服务器通过该合同举行通讯,由客户端发送出电子邮件,SMTP服务器通过网络上其余SMTP服务器,最后将邮件传递到收信人的邮件服务器。本程序作为电子邮件顾客端程序,最基本的意义是要贯彻电子邮件发送,为了简化编制程序,使用了Delphi自带的TNMSMTP控件,该控件封装了对SMTP编制程序。由于该控件世袭自TPowersock,因此必要时能够直接调用底层的Socket进程,又不失灵活性。
  比方,尽管TNMSMTP不直接扶持“SMTP服务器认证成效”,不过,能够采纳TNMSMTP的Connect事件和持续自TPowersock的Transaction方法,达成SMTP服务器认证。其原理在于,Connect事件发生在TNMSMTP与服务器连接成功之时,当时,使用Transaction方法发生SMTP服务器认证所鲜明的“AUTH LOGIN”命令,并输入经过BASE64编码后的客户名和密码,能够兑现认证。由此,本程序完毕了SMTP服务器认证。
  其它,TNMSMTP的SendStart事件在邮件发送早先时接触,在该事件中,能够因而改革TNMSMTP的FinalHeader属性值,实现修改电子邮件的邮件头音讯。在本程序中须要改正邮件头的Content-Type属性,使选拔嵌入Flash动画电子邮件的客商端软件(如Foxmail卡塔尔国能精确管理邮件内容。
2.MIME协议
  最近,大致拥有的邮件服务器和顾客端软件都支持“多用场Internet邮件扩张”左券Multipurpose Internet Mail Extensions (MIME)。该合同的新式版由KoleosFC2045(Internet新闻体魄式卡塔 尔(英语:State of Qatar)、ENVISIONFC2046(媒体类型卡塔 尔(阿拉伯语:قطر‎、ENVISIONFC2047(无ASCII文本新闻头扩张卡塔尔国、PAJEROFC2048(注册进程卡塔 尔(英语:State of Qatar)、RAV4FC2049(生龙活虎致性标准和例子卡塔 尔(英语:State of Qatar)等大器晚成并明确。该契约遵从了帕杰罗FC82第22中学规定的电子邮件内容只好满含简单的ASCII文本字符(如字母、数字、标点符号等卡塔尔国,定义了在电子邮件中回顾经过编码的二进制文件的情势,编码后的开始和结果将只富含文件字符。近日,完结对二进制文件编码的正式有无数,BASE64编码标准也是中间之风流倜傥。本程序使用TMemoryStream对象,完结了通用的BASE64编码函数EncodeBASE64,能够对SWF文件举办编码。
  通过MIME协议,电子邮件中不只好够加上附属类小构件,还足以增加HTML格式内容,满含图片、声音、动画等。Outlook、Foxmail等软件都得以编写制定HTML格式的邮件,可是并不帮衬直接嵌入Flash动漫。事实上,正确使用MIME合同,能够在HTML格式的邮件中嵌入Flash动漫,并在邮件正文中展现出来,其规律和在HTML格式邮件中显得图片、播放音响是一模二样的。在HTML格式邮件中嵌入Flash动漫与向网页中增加动漫所急需的代码是如出大器晚成辙的,相像接受< OBJECT >、< EMBED >标志,感兴趣的相恋的人能够查看三个分包Flash动漫的网页源代码,相比较本程序。
  在本程序中,设置邮件MIME音讯头的Content-Type属性为multipart/related; boundary="---SwfEmail by JDH",表示该邮件包含三个例外数据类型的部分,各样部分之间用"---SwfEmail by JDH"(不包涵引号卡塔 尔(英语:State of Qatar)区分。在邮件内容的这一个片段中,依据每部分的内容不生龙活虎,再为其丰硕相应的MIME新闻头,具体可参见程序源代码。

WideString保存为文本文件时,常用的有UTF-8、Unicode、Ansi、Unicode Big Endian,
其间 UTF-8 的格式,从文件读取的时候,要求使用 Delphi7 提供的 Utf8ToUnicode
退换一下全体编码,别的二种编码自个儿都无需更动(BigEndian编码是索尼爱立信专门的工作,是
intel 规范的 Unicode (即大家后天说的 WideString)编码的字符按字节反转,那切合摩
Toro拉坐蓐的微计算机微电路的结构特点,所以读取后要按 WOKoleosD 反转卡塔 尔(阿拉伯语:قطر‎,但保留为相应格式的
文件文件时,必需按必要在文书尾部写入贰个编码识别标记,他们各自为:

实现:

二、编制程序实战
  运行Delphi,在Form1上开创各类控件。在那之中txt前缀表示TEdit控件,mem前缀表示TMemo控件,chk前缀表示TCheckbox控件,btn前缀表示TButton控件,NMSMTP1是TNMSMTP控件,OpenDialog1是TOpenDialog控件。

Ansi:不需要
Unicode:$FEFF (十三进制编辑器看到的是高位在前展示$FFFE,以下同卡塔 尔(英语:State of Qatar)
BigEndian:$FFFE (正巧是地点 Unicode 的反转卡塔 尔(阿拉伯语:قطر‎
UTF-8:$BBEF $BF (三字节,十二进制编辑器里展现 $EFBB BF卡塔 尔(阿拉伯语:قطر‎

1、在NMSMTP的OnConnect事件中增添代码:

未来加上代码如下:
{******Unit1.pas源代码内容如下******}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Psock, NMsmtp;
type

如此,其余编辑器读取时就足以辨认出保存者把文件翻译成了怎么编码。
Unicode(即WideString卡塔 尔(英语:State of Qatar)只要写好文件头,前面包车型地铁就遵照保存Ansi文本一样把
文件写入文件,保存为Big Endian,则按WO宝马X5D逐字节反转写入,保存为UTF-8
要运用UnicodeToUtf8调换后写入。

var  strUserName, strPassword: String;
begin
  strUserName := EncodeString(CoolSlob);//CoolSlob是服务器的帐号
  strPassword := EncodeString(Password);//Password是密码
  {实行认证,输入编码后的顾客名、密码}
  nmsmtp1.Transaction(EHLO) ;
  nmsmtp1.Transaction(AUTH LOGIN);
  nmsmtp1.Transaction(strUserName);
  nmsmtp1.Transaction(strPassword);
  StatusBar1.SimpleText := 连接成功;
end;

......
procedure TForm1.btnOpenClick(Sender: TObject);
begin
{张开对话框,选取SWF文件}
if OpenDialog1.Execute then

在XML拆解解析中,借使带有非ASCII编码的文字,MS暗中认可使用UTF-16编码,假诺
原始文本是Ansi编码,这个时候将赢得乱码的字符。那么些编码不是Delphi形成的,是
MS的XML库所致,所以在动用非ASCII字符前,建议调换到UTF-8编码,下面例
子中自己尚未运用WideString,所以并未有贯彻编码转变。

2、EncodeString函数实现进程:

procedure TForm1.NMSMTP1SendStart(Sender: TObject);
begin
{在邮件发送伊始时校订邮件的音信头,标记邮件为多一些组成}
NMSMTP1.FinalHeader.Values[Content-Type] := multipart/related; boundary="------------SwfEmail by JDH";
end;

编码转换有过多现有的开源代码能够行使,此中国电影响最深刻的就是JEDI的Unicoee.pas,
但那么些文件很宏大,大概有250K大小,它还含有一个转变表的能源文件,假设
拍卖部分小型的字符转换就显得杀鸡用牛刀了。当然我们能够直接运用Delphi7
提供给我们的函数,比如:

{对参数Decoded字符串举行Base64编码,重临编码后的字符串}
function EncodeString(Decoded:string):String;
var
    mmTemp,mmDecoded:TMemoryStream;
    strTemp:TStrings;
begin
    mmTemp := TMemoryStream.Create;
    mmDecoded:=TMemoryStream.Create;
    strTemp:=TStringList.Create;
    strTemp.Add(Decoded);
    strTemp.SaveToStream(mmTemp);
    mmTemp.Position := 0;
    {剔除mmTemp从strTemp中拉动的字符#13#10}
    mmDecoded.CopyFrom(mmTemp,mmTemp.Size-2);
    {对mmDecoded实行Base64编码,由mmTemp重回编码后的结果}
    EncodeBASE64(mmTemp,mmDecoded);
    {获得Base64编码后的字符串}
    mmTemp.Position:=0;
    strTemp.LoadFromStream(mmTemp);
    {重回结果必须从strTemp[0]中获得,借使运用strTemp.Text会
    带来无需的字符#13#10}
    Result:=strTemp[0];
end;

procedure TForm1.chkSmtpVerifyClick(Sender: TObject);
begin
{根据是不是供给SMTP服务器认证,退换客户名、密码状态}
if chkSmtpVerify.Checked = True then

function PUCS4Chars(const S: UCS4String): PUCS4Char;

3、EncodeBASE64函数完毕进度:

......
三、程序运维

function WideStringToUCS4String(const S: WideString): UCS4String;
function UCS4StringToWidestring(const S: UCS4String): WideString;

function EncodeBASE64(Encoded: TMemoryStream ; Decoded: TMemoryStream): Integer;
const
    _Code64: String[64] =
        (ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 /);
var
    I: LongInt;
    B: array[0..2279] of Byte;
    J, K, L, M, Quads: Integer;
    Stream: string[76];
    EncLine: String;
begin
    Encoded.Clear;
    Stream := ;
    Quads := 0;
    {为升高功效,每2280字节流为豆蔻梢头组举办编码}
    J := Decoded.Size div 2280;
    Decoded.Position := 0;
    {对前J*2277个字节流进行编码}
    for I := 1 to J do
    begin
        Decoded.Read(B, 2280);
        for M := 0 to 39 do
        begin
            for K := 0 to 18 do
            begin
                L:= 57*M 3*K;
                Stream[Quads 1] := _Code64[(B[L] div 4) 1];
                Stream[Quads 2] := _Code64[(B[L] mod 4)*16 (B[L 1] div 16) 1];
                Stream[Quads 3] := _Code64[(B[L 1] mod 16)*4 (B[L 2] div 64) 1];
                Stream[Quads 4] := _Code64[B[L 2] mod 64 1];
                Inc(Quads, 4);
                if Quads = 76 then
                begin
                    Stream[0] := #76;
                    EncLine := Stream #13#10;
                    Encoded.Write(EncLine[1], Length(EncLine));
                    Quads := 0;
                end;
            end;
        end;
    end;

  首先在Delphi中编译运营,接着在对话框中输入收信人、发信人、主旨、正文内容以致SMTP服务器,比方填写“smtp.263.net”,端口号使用私下认可的25,选中“SMTP服务器需求表明”,并依靠发信人输入客商名、密码。单击“张开文件”按键,选用要发送的Flash动漫文件,确认正确后,单击“发送”按键就能够。发送成功后,相会世发信成功

function UnicodeToUtf8(Dest: PChar; Source: PWideChar; MaxBytes: Integer): Integer;
function UnicodeToUtf8(Dest: PChar; MaxDestBytes: Cardinal; Source: PWideChar; SourceChars: Cardinal): Cardinal;

    {对以2280为模的余数字节流举办编码}
    J := (Decoded.Size mod 2280) div 3;
    for I := 1 to J do
    begin
        Decoded.Read(B, 3);
        Stream[Quads 1] := _Code64[(B[0] div 4) 1];
        Stream[Quads 2] := _Code64[(B[0] mod 4)*16 (B[1] div 16) 1];
        Stream[Quads 3] := _Code64[(B[1] mod 16)*4 (B[2] div 64) 1];
        Stream[Quads 4] := _Code64[B[2] mod 64 1];
        Inc(Quads, 4);
        {每行76个字符}
        if Quads = 76 then
        begin
            Stream[0] := #76;
            EncLine := Stream #13#10;
            Encoded.Write(EncLine[1], Length(EncLine));
            Quads := 0;
        end;
    end;
    {“=”补位}
    if (Decoded.Size mod 3) = 2 then
    begin
        Decoded.Read(B, 2);
        Stream[Quads 1] := _Code64[(B[0] div 4) 1];
        Stream[Quads 2] := _Code64[(B[0] mod 4)*16 (B[1] div 16) 1];
        Stream[Quads 3] := _Code64[(B[1] mod 16)*4 1];
        Stream[Quads 4] := =;
        Inc(Quads, 4);
    end;

Delphi让您发送Flash电子邮件完整源代码:

function Utf8ToUnicode(Dest: PWideChar; Source: PChar; MaxChars: Integer): Integer;
function Utf8ToUnicode(Dest: PWideChar; MaxDestChars: Cardinal; Source: PChar; SourceBytes: Cardinal): Cardinal;

    if (Decoded.Size mod 3) = 1 then
    begin
        Decoded.Read(B, 1);
        Stream[Quads 1] := _Code64[(B[0] div 4) 1];
        Stream[Quads 2] := _Code64[(B[0] mod 4)*16 1];
        Stream[Quads 3] := =;
        Stream[Quads 4] := =;
        Inc(Quads, 4);
    end;

{******Unit1.pas源代码内容如下******}
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls, Psock, NMsmtp;
type
TForm1 = class(TForm)
Label1: TLabel;
txtTo: TEdit;
Label2: TLabel;
txtFrom: TEdit;
Label3: TLabel;
txtSubject: TEdit;
Label4: TLabel;
memContents: TMemo;
Label5: TLabel;
txtUserName: TEdit;
Label6: TLabel;
txtPassword: TEdit;
chkSmtpVerify: TCheckBox;
btnSend: TButton;
btnOpen: TButton;
txtSwfFile: TEdit;
Label7: TLabel;
OpenDialog1: TOpenDialog;
Label8: TLabel;
txtSmtpServer: TEdit;
NMSMTP1: TNMSMTP;
Label9: TLabel;
txtPort: TEdit;
procedure btnOpenClick(Sender: TObject);
procedure btnSendClick(Sender: TObject);
procedure NMSMTP1SendStart(Sender: TObject);
procedure NMSMTP1Connect(Sender: TObject);
procedure chkSmtpVerifyClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

function Utf8Encode(const WS: WideString): UTF8String;
function Utf8Decode(const S: UTF8String): WideString;

    Stream[0] := Chr(Quads);
    if Quads > 0 then
    begin
        EncLine := Stream #13#10;
        Encoded.Write(EncLine[1], Length(EncLine));
    end;

var
Form1: TForm1;
function EncodeString(Decoded:string):String;
function EncodeBASE64(Encoded: TMemoryStream {TMailText}; Decoded: TMemoryStream): Integer; //编码函数
implementation
{$R *.dfm}
{对参数TMemoryStrema中的字节流举行Base64编码,编码后的结果
封存在Encoded中,函数再次回到编码长度}
function EncodeBASE64(Encoded: TMemoryStream ; Decoded: TMemoryStream): Integer;
const
_Code64: String[64] =
(ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 /);
var
I: LongInt;
B: array[0..2279] of Byte;
J, K, L, M, Quads: Integer;
Stream: string[76];
EncLine: String;
begin
Encoded.Clear;
Stream := ;
Quads := 0;
{为提升功能,每2280字节流为生机勃勃组开展编码}
J := Decoded.Size div 2280;
Decoded.Position := 0;
{对前J*22八十个字节流进行编码}
for I := 1 to J do
begin
Decoded.Read(B, 2280);
for M := 0 to 39 do
begin
for K := 0 to 18 do
begin
L:= 57*M 3*K;
Stream[Quads 1] := _Code64[(B[L] div 4) 1];
Stream[Quads 2] := _Code64[(B[L] mod 4)*16 (B[L 1] div 16) 1];
Stream[Quads 3] := _Code64[(B[L 1] mod 16)*4 (B[L 2] div 64) 1];
Stream[Quads 4] := _Code64[B[L 2] mod 64 1];
Inc(Quads, 4);
if Quads = 76 then
begin
Stream[0] := #76;
EncLine := Stream #13#10;
Encoded.Write(EncLine[1], Length(EncLine));
Quads := 0;
end;
end;
end;
end;

function AnsiToUtf8(const S: string): UTF8string;
function Utf8ToAnsi(const S: UTF8string): string;

 &

{对以2280

等等。这几个早就足足使用了。轻量级的代码是OmniXML中的TGpTextStream,
然而那么些代码有众多BUG,而且不帮助BigEndian的写入(读取部分也因忘了使
用有时变量而不当卡塔 尔(阿拉伯语:قطر‎。那一个都得以利用。

现在许多STMP服务器在发送邮件时均需另行认证二遍,而Delphi的TNMSMTP控件对它并未有很“可视化”的帮忙,使众几人在支付进度中山高校打...

论 Outlook XP照旧福克斯mail,都必须要在HTML格式的电子邮件中存放JPG、GIF格式图片,而音色俱佳的Flash动漫却只好当作电子邮件附件发送给很好的朋友,...

在Delphi7中,艾德it等控件不支持WideString,但有豆蔻梢头组TnTWare的开源控件可
以直接扶植WideString。

本文由新浦京81707con发布于功能介绍,转载请注明出处:谈谈字符编码,使用TNMSMTP控件在需认证服务器上

关键词: 新浦京81707con Delphi

上一篇:伪分布模式安装Hadoop,入门伪分布式配置

下一篇:没有了