工作中有个需求需要发送邮件,因为使用的delphi6,所以自然就选择了indy组件,想想这事挺简单的。实现的过程倒是简单,看着Indy的demo很快就完了,毕竟也不是很复杂的功能。
功能要求:
1、压缩日志文件并作为邮件的附件
2、邮件正文带上一些客户端信息
组件介绍
TIdSmtp:与服务器的连接及数据发送,基于smtp协议
TIdMessage:自然就是报文的信息了,包含收件人、发件人、主题、正文,以及附件。
代码展示:
function TfrmMailSend.SendMail: Boolean;
var
objMailBody: TStrings;
begin
Result := False;
IdSMTP1.Username := FMailSetting.Username;
IdSMTP1.Password := FMailSetting.Password;
IdSMTP1.Host := FMailSetting.Host;
IdSMTP1.Port := FMailSetting.Port;
IdSMTP1.AuthenticationType := atLogin;
IdMessage1.Priority := mpNormal;
IdMessage1.From.Text := FMailSetting.FromAddress;
IdMessage1.Recipients.EMailAddresses := edtToAddress.Text;
IdMessage1.Subject := '日志:'+FormatDateTime('YYYY-MM-DD', dtpLogDate.Date) + '['+hsGetOperatorNo+']';
objMailBody := TStringList.Create;
try
objMailBody.Add('<table>');
objMailBody.Add('<tr><td><b>ClientID:</b></td><td>'+ hsGetClientID + '</td></tr>');
objMailBody.Add('<tr><td><b>CompanyName:</b></td><td>'+ AnsiToUtf8('中文革') + '</td></tr>');
objMailBody.Add('<tr><td><b>Server DateTime:</b></td><td>'+ DateTimeToStr(GetServerDateTime) + '</td></tr>');
objMailBody.Add('</table>');
//可能是Indy的bug,需要创建两次TIdText才能成功发送内容
with TIdText.Create(IdMessage1.MessageParts, objMailBody) do
begin
ContentType:='text/html;charset=utf-8';
ContentTransfer := 'quoted-printable'; //不能用base64,indy控件没实现
end;
with TIdText.Create(IdMessage1.MessageParts, objMailBody) do
begin
ContentType := 'text/html;charset=utf-8';
ContentTransfer := 'quoted-printable'; //不能用base64,indy控件没实现
end;
finally
FreeAndNil(objMailBody);
end;
try
IdSMTP1.Connect;
try
IdSMTP1.Send(IdMessage1);
Result := True;
finally
if IdSMTP1.Connected then
IdSMTP1.Disconnect;
end;
except
on e: Exception do
Console('[发送异常]'+e.Message);
end;
end;
代码流程主要是先准备好smtp主机信息,用户名与密码。然后组织好邮件内容,然后连接并发送。
关于附件
附件添加比较简单,Indy封装了一个专门的消息类TIdAttachment,只要将文件用TIdAttachment附加即可:
TIdAttachment.Create(IdMessage1.MessageParts, AFileName);
这样就可以将附件添加到邮件人内容中了。
解决中文乱码问题
写这个小程序最头痛的就是中文乱码问题,由于对这个组件不熟悉,找了半天也没找到办法解决。因为delphi早期版本一直都是基于ansi字符集,所以对于中文需要支持时就得专门处理。对email的协议也不太熟悉,只知道是编码问题,但找了老半天也没找到相着的解决方法。设置了IdMessage的CharSet也没有效果。
于是没办法就只要查看foxmail,QQ邮箱之类的邮件原文来看看差别。发现主要是三个点:
Content-Type: text/html;
charset="GB2312"
Content-Transfer-Encoding: quoted-printable
对于前两个好理解,和html协议类似。但Content-Transfer-Encoding没怎么接触过。
Content-Transfer-Encoding主要值:
7bit:用于不编码的数据。数据为 7 位 US-ASCII 字符,总行长不超过 1000 个字符。
base64:不用解释了。这个通常用于字节流,比较附件就用这个格式。
quoted-printable:将由 US-ASCII 字符集中可打印的字符组成的数据编码。
之所以是中文乱码,原因是添加邮件正文时的字符集与接收邮件客户端的字符集对上。比如Delphi默认发送的时候文本是Ansi的,结果Foxmail却是不支持。只有GB2312、UTF-8之类的。查看邮件正文:
Content-Type: text/html;
charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
这样一来肯定就显示乱码了,因为发的时候他中文并不是UTF-8的格式。解决这个问题办法也简单,那就把字符串转正特定的编码再发吧。
还好delphi里有个函数直接就用:
这样发过去的内容中文就可以显示了。
发送Html
直接在TIdMessage的body内容发送其实是text/plain,这种明格式的话就不太