无法使用 TIdSMTP 发送 UTF-8 消息
Cannot send UTF-8 message with TIdSMTP
我有发送邮件的按钮:
procedure TRealization.Button17Click(Sender: TObject);
var
EmailCore: TStringStream;
EmailBody, sInvoices: string;
FilePath: string;
MailTitle: string;
i: integer;
begin
if (Languages.ItemIndex > -1) then begin
EmailCore := TStringStream.Create('', TEncoding.UTF8);
if Languages.ItemIndex = 0 then begin
FilePath := ExtractFilePath(Application.ExeName)+'/languages/pl.html';
MailTitle := 'Płatność dla '+Monitoring.l_client_name.Caption;
end else if Languages.ItemIndex = 1 then begin
FilePath := ExtractFilePath(Application.ExeName)+'/languages/en.html';
MailTitle := 'Invoice payment for '+Monitoring.l_client_name.Caption;
end;
EmailCore.LoadFromFile(FilePath);
for i := 0 to (preview_invoices.RowCount-1) do begin
sInvoices := sInvoices+'<tr><td>'+preview_invoices.Cells[2,i]+'</td><td>'+preview_invoices.Cells[4,i]+'</td><td>'+preview_invoices.Cells[4,i]+'</td><td>'+preview_invoices.Cells[5,i]+'</td><td>'+preview_invoices.Cells[6,i]+'</td></tr>';
end;
EmailBody := StringReplace(EmailCore.DataString, ':LIST:', sInvoices, [rfReplaceAll]);
EmailBody := StringReplace(EmailBody, ':COMPANY:', Monitoring.l_client_name.Caption, [rfReplaceAll]);
EmailBody := StringReplace(EmailBody, ':VAT:', Monitoring.l_client_vat.Caption, [rfReplaceAll]);
EmailBody := StringReplace(EmailBody, ':NAME:', Main.l_uname.Caption, [rfReplaceAll]);
Main.SendEmailIndy('my.mail.com',
Main.l_uname.Caption,
_GlobalData.EMail,
Emails.Text,
_GlobalData.EMail,
'',
MailTitle,
EMailBody,
true,
nil);
EmailCore.Free;
end;
end;
这是发送函数 e-mails:
procedure TMain.SendEmailIndy(
const SMTPServer: string;
const FromName, FromAddress: string;
const ToAddresses: string; //comma "," separated list of e-mail addresses
const CCAddresses: string; //comma "," separated list of e-mail addresses
const BCCAddresses: string; //comma "," separated list of e-mail addresses
const Subject: string;
const EmailBody: string;
const IsBodyHtml: Boolean; //verses Plain Text
const Attachments: TStrings);
var
smtp: TIdSMTP; // IdSmtp.pas
msg: TidMessage; // IdMessage.pas
builder: TIdCustomMessageBuilder; //IdMessageBuilder.pas
s: string;
emailAddress: string;
begin
msg := TidMessage.Create(nil);
msg.Encoding := meMIME;
msg.ContentType := 'text/html';
msg.CharSet := 'UTF-8';
msg.ContentTransferEncoding:= 'quoted-printable';
try
if IsBodyHtml then begin
builder := TIdMessageBuilderHtml.Create;
TIdMessageBuilderHtml(builder).Html.Text := EmailBody
end else begin
builder := TIdMessageBuilderPlain.Create;
end;
try
if Attachments <> nil then
begin
for s in Attachments do
builder.Attachments.Add(s);
end;
builder.FillMessage(msg);
finally
builder.Free;
end;
msg.From.Name := FromName;
msg.From.Address := FromAddress;
msg.Subject := Subject;
//If the message is plaintext then we must fill the body outside of the PlainText email builder.
//(the PlainTextBuilder is unable to build plaintext e-mail)
if not IsBodyHtml then begin
msg.Body.Text := EmailBody;
end;
for s in ToAddresses.Split([',']) do
begin
emailAddress := Trim(s);
if emailAddress <> '' then
begin
with msg.recipients.Add do
begin
//Name := '<Name of recipient>';
Address := emailAddress;
end;
end;
end;
for s in CCAddresses.Split([',']) do
begin
emailAddress := Trim(s);
if emailAddress <> '' then
msg.CCList.Add.Address := emailAddress;
end;
for s in BCCAddresses.Split([',']) do
begin
emailAddress := Trim(s);
if emailAddress <> '' then
msg.BccList.Add.Address := emailAddress;
end;
smtp := TIdSMTP.Create(nil);
try
smtp.Host := SMTPServer; // IP Address of SMTP server
Smtp.UseTLS := utNoTLSSupport;
smtp.Port := 587; //The default already is port 25 (the SMTP port)
smtp.Username := _GlobalData.EMail;
smtp.Password := _GlobalData.Password;
//Indy (and C# SmtpClient class) already defaults to the computer name
//smtp.HeloName :=
smtp.Connect;
try
smtp.Send(msg);
ShowMessage('Wiadomość wysłana.');
log('EMAIL', 'Wysłano zapytanie do '+ToAddresses, StrToInt(Monitoring.t_mid.Caption));
finally
//smtp.Disconnect();
end;
finally
//smtp.Free;
end;
finally
//msg.Free;
end;
end;
问题是,当我收到一封电子邮件时,body(e-mail 标题实际上没问题,可以显示所有字符)包含问号,其中波兰语或德语字母是(±、ż、 ó, ę, ö, ä 等)。邮件编码错误。我尝试使用 UTF8Encode 和此处找到的其他解决方案,但实际上没有任何效果。 E-mails 继续发送损坏的内容。
如有任何帮助,我将不胜感激。
您对 TIdMessage.CharSet
的分配被忽略,因为 TIdMessageBuilder
重置了 CharSet
(以及 ContentType
、ContentTransferEncoding
和 Encoding
属性) 在填充 TIdMessage
.
之前
因此,您需要改为设置 TIdMessageBuilderPlain.PlainTextCharSet
和 TIdMessageBuilderHtml.HtmlCharSet
属性。
此外,您不需要单独使用 TIdMessageBuilderPlain
和 TIdMessageBuilderHtml
。您可以单独使用 TIdMessageBuilderHtml
,因为它可以创建纯文本和 HTML 电子邮件,具体取决于填充的属性。您的评论“如果邮件是明文,那么我们必须在 PlainText 电子邮件生成器之外填充正文。PlainTextBuilder 无法构建明文电子邮件”是完全不正确的,如中所述my blog article on how to use TIdMessageBuilderHtml
.
试试这个功能代码:
procedure TMain.SendEmailIndy(
const SMTPServer: string;
const FromName, FromAddress: string;
const ToAddresses: string; //comma "," separated list of e-mail addresses
const CCAddresses: string; //comma "," separated list of e-mail addresses
const BCCAddresses: string; //comma "," separated list of e-mail addresses
const Subject: string;
const EmailBody: string;
const IsBodyHtml: Boolean; //verses Plain Text
const Attachments: TStrings);
var
smtp: TIdSMTP; // IdSmtp.pas
msg: TidMessage; // IdMessage.pas
builder: TIdMessageBuilderHtml; //IdMessageBuilder.pas
s: string;
emailAddress: string;
begin
msg := TIdMessage.Create(nil);
try
builder := TIdMessageBuilderHtml.Create;
try
if IsBodyHtml then
begin
builder.Html.Text := EmailBody;
builder.HtmlCharSet := 'utf-8';
end else
begin
builder.PlainText.Text := EmailBody;
builder.PlainTextCharSet := 'utf-8';
end;
if Attachments <> nil then
begin
for s in Attachments do
builder.Attachments.Add(s);
end;
builder.FillMessage(msg);
finally
builder.Free;
end;
msg.From.Name := FromName;
msg.From.Address := FromAddress;
msg.Subject := Subject;
msg.Recipients.EmailAddresses := ToAddresses;
msg.CCList.EmailAddresses := CCAddresses;
msg.BccList.EmailAddresses := BCCAddresses;
smtp := TIdSMTP.Create(nil);
try
smtp.Host := SMTPServer; // IP Address of SMTP server
smtp.UseTLS := utNoTLSSupport;
smtp.Port := 587; //The default already is port 25 (the SMTP port)
smtp.Username := _GlobalData.EMail;
smtp.Password := _GlobalData.Password;
//Indy (and C# SmtpClient class) already defaults to the computer name
//smtp.HeloName :=
smtp.Connect;
try
smtp.Send(msg);
log('EMAIL', 'Wysłano zapytanie do '+ToAddresses, StrToInt(Monitoring.t_mid.Caption));
finally
smtp.Disconnect;
end;
ShowMessage('Wiadomość wysłana.');
finally
smtp.Free;
end;
finally
msg.Free;
end;
end;
此外,仅供参考,如果您使用 UseTLS=utNoTLSSupport
,那么您应该使用 Port=25
。如果你想使用 Port=587
那么你应该使用 UseTLS=utUseExplicitTLS
(这需要将 SSLIOHandler
分配给 TIdSMTP.IOHandler
属性,例如 TIdSSLIOHandlerSocketOpenSSL
).
我有发送邮件的按钮:
procedure TRealization.Button17Click(Sender: TObject);
var
EmailCore: TStringStream;
EmailBody, sInvoices: string;
FilePath: string;
MailTitle: string;
i: integer;
begin
if (Languages.ItemIndex > -1) then begin
EmailCore := TStringStream.Create('', TEncoding.UTF8);
if Languages.ItemIndex = 0 then begin
FilePath := ExtractFilePath(Application.ExeName)+'/languages/pl.html';
MailTitle := 'Płatność dla '+Monitoring.l_client_name.Caption;
end else if Languages.ItemIndex = 1 then begin
FilePath := ExtractFilePath(Application.ExeName)+'/languages/en.html';
MailTitle := 'Invoice payment for '+Monitoring.l_client_name.Caption;
end;
EmailCore.LoadFromFile(FilePath);
for i := 0 to (preview_invoices.RowCount-1) do begin
sInvoices := sInvoices+'<tr><td>'+preview_invoices.Cells[2,i]+'</td><td>'+preview_invoices.Cells[4,i]+'</td><td>'+preview_invoices.Cells[4,i]+'</td><td>'+preview_invoices.Cells[5,i]+'</td><td>'+preview_invoices.Cells[6,i]+'</td></tr>';
end;
EmailBody := StringReplace(EmailCore.DataString, ':LIST:', sInvoices, [rfReplaceAll]);
EmailBody := StringReplace(EmailBody, ':COMPANY:', Monitoring.l_client_name.Caption, [rfReplaceAll]);
EmailBody := StringReplace(EmailBody, ':VAT:', Monitoring.l_client_vat.Caption, [rfReplaceAll]);
EmailBody := StringReplace(EmailBody, ':NAME:', Main.l_uname.Caption, [rfReplaceAll]);
Main.SendEmailIndy('my.mail.com',
Main.l_uname.Caption,
_GlobalData.EMail,
Emails.Text,
_GlobalData.EMail,
'',
MailTitle,
EMailBody,
true,
nil);
EmailCore.Free;
end;
end;
这是发送函数 e-mails:
procedure TMain.SendEmailIndy(
const SMTPServer: string;
const FromName, FromAddress: string;
const ToAddresses: string; //comma "," separated list of e-mail addresses
const CCAddresses: string; //comma "," separated list of e-mail addresses
const BCCAddresses: string; //comma "," separated list of e-mail addresses
const Subject: string;
const EmailBody: string;
const IsBodyHtml: Boolean; //verses Plain Text
const Attachments: TStrings);
var
smtp: TIdSMTP; // IdSmtp.pas
msg: TidMessage; // IdMessage.pas
builder: TIdCustomMessageBuilder; //IdMessageBuilder.pas
s: string;
emailAddress: string;
begin
msg := TidMessage.Create(nil);
msg.Encoding := meMIME;
msg.ContentType := 'text/html';
msg.CharSet := 'UTF-8';
msg.ContentTransferEncoding:= 'quoted-printable';
try
if IsBodyHtml then begin
builder := TIdMessageBuilderHtml.Create;
TIdMessageBuilderHtml(builder).Html.Text := EmailBody
end else begin
builder := TIdMessageBuilderPlain.Create;
end;
try
if Attachments <> nil then
begin
for s in Attachments do
builder.Attachments.Add(s);
end;
builder.FillMessage(msg);
finally
builder.Free;
end;
msg.From.Name := FromName;
msg.From.Address := FromAddress;
msg.Subject := Subject;
//If the message is plaintext then we must fill the body outside of the PlainText email builder.
//(the PlainTextBuilder is unable to build plaintext e-mail)
if not IsBodyHtml then begin
msg.Body.Text := EmailBody;
end;
for s in ToAddresses.Split([',']) do
begin
emailAddress := Trim(s);
if emailAddress <> '' then
begin
with msg.recipients.Add do
begin
//Name := '<Name of recipient>';
Address := emailAddress;
end;
end;
end;
for s in CCAddresses.Split([',']) do
begin
emailAddress := Trim(s);
if emailAddress <> '' then
msg.CCList.Add.Address := emailAddress;
end;
for s in BCCAddresses.Split([',']) do
begin
emailAddress := Trim(s);
if emailAddress <> '' then
msg.BccList.Add.Address := emailAddress;
end;
smtp := TIdSMTP.Create(nil);
try
smtp.Host := SMTPServer; // IP Address of SMTP server
Smtp.UseTLS := utNoTLSSupport;
smtp.Port := 587; //The default already is port 25 (the SMTP port)
smtp.Username := _GlobalData.EMail;
smtp.Password := _GlobalData.Password;
//Indy (and C# SmtpClient class) already defaults to the computer name
//smtp.HeloName :=
smtp.Connect;
try
smtp.Send(msg);
ShowMessage('Wiadomość wysłana.');
log('EMAIL', 'Wysłano zapytanie do '+ToAddresses, StrToInt(Monitoring.t_mid.Caption));
finally
//smtp.Disconnect();
end;
finally
//smtp.Free;
end;
finally
//msg.Free;
end;
end;
问题是,当我收到一封电子邮件时,body(e-mail 标题实际上没问题,可以显示所有字符)包含问号,其中波兰语或德语字母是(±、ż、 ó, ę, ö, ä 等)。邮件编码错误。我尝试使用 UTF8Encode 和此处找到的其他解决方案,但实际上没有任何效果。 E-mails 继续发送损坏的内容。
如有任何帮助,我将不胜感激。
您对 TIdMessage.CharSet
的分配被忽略,因为 TIdMessageBuilder
重置了 CharSet
(以及 ContentType
、ContentTransferEncoding
和 Encoding
属性) 在填充 TIdMessage
.
因此,您需要改为设置 TIdMessageBuilderPlain.PlainTextCharSet
和 TIdMessageBuilderHtml.HtmlCharSet
属性。
此外,您不需要单独使用 TIdMessageBuilderPlain
和 TIdMessageBuilderHtml
。您可以单独使用 TIdMessageBuilderHtml
,因为它可以创建纯文本和 HTML 电子邮件,具体取决于填充的属性。您的评论“如果邮件是明文,那么我们必须在 PlainText 电子邮件生成器之外填充正文。PlainTextBuilder 无法构建明文电子邮件”是完全不正确的,如中所述my blog article on how to use TIdMessageBuilderHtml
.
试试这个功能代码:
procedure TMain.SendEmailIndy(
const SMTPServer: string;
const FromName, FromAddress: string;
const ToAddresses: string; //comma "," separated list of e-mail addresses
const CCAddresses: string; //comma "," separated list of e-mail addresses
const BCCAddresses: string; //comma "," separated list of e-mail addresses
const Subject: string;
const EmailBody: string;
const IsBodyHtml: Boolean; //verses Plain Text
const Attachments: TStrings);
var
smtp: TIdSMTP; // IdSmtp.pas
msg: TidMessage; // IdMessage.pas
builder: TIdMessageBuilderHtml; //IdMessageBuilder.pas
s: string;
emailAddress: string;
begin
msg := TIdMessage.Create(nil);
try
builder := TIdMessageBuilderHtml.Create;
try
if IsBodyHtml then
begin
builder.Html.Text := EmailBody;
builder.HtmlCharSet := 'utf-8';
end else
begin
builder.PlainText.Text := EmailBody;
builder.PlainTextCharSet := 'utf-8';
end;
if Attachments <> nil then
begin
for s in Attachments do
builder.Attachments.Add(s);
end;
builder.FillMessage(msg);
finally
builder.Free;
end;
msg.From.Name := FromName;
msg.From.Address := FromAddress;
msg.Subject := Subject;
msg.Recipients.EmailAddresses := ToAddresses;
msg.CCList.EmailAddresses := CCAddresses;
msg.BccList.EmailAddresses := BCCAddresses;
smtp := TIdSMTP.Create(nil);
try
smtp.Host := SMTPServer; // IP Address of SMTP server
smtp.UseTLS := utNoTLSSupport;
smtp.Port := 587; //The default already is port 25 (the SMTP port)
smtp.Username := _GlobalData.EMail;
smtp.Password := _GlobalData.Password;
//Indy (and C# SmtpClient class) already defaults to the computer name
//smtp.HeloName :=
smtp.Connect;
try
smtp.Send(msg);
log('EMAIL', 'Wysłano zapytanie do '+ToAddresses, StrToInt(Monitoring.t_mid.Caption));
finally
smtp.Disconnect;
end;
ShowMessage('Wiadomość wysłana.');
finally
smtp.Free;
end;
finally
msg.Free;
end;
end;
此外,仅供参考,如果您使用 UseTLS=utNoTLSSupport
,那么您应该使用 Port=25
。如果你想使用 Port=587
那么你应该使用 UseTLS=utUseExplicitTLS
(这需要将 SSLIOHandler
分配给 TIdSMTP.IOHandler
属性,例如 TIdSSLIOHandlerSocketOpenSSL
).