Pull to refresh

С++ Builder и отправка почты с использованием Indy 10

Однажды встала необходимость написания программы, которая бы отправляла письма организациям без участия пользователя. Требовалось создать «экзешник», который бы все делал и не требовал установки NET.Framework. Единственным инструментом, который был под рукой и подходил для этого стал RAD Studio 2009 C++ Builder.
Т.к до этого я ничего подобного не писал, да и с Indy работать как-то не приходилось, то полез в Интернет, в надежде найти ответ на мой вопрос. Но, порыскав в нем и прочитав огромное количество постов на многочисленных форумах, стало ясно, что ни один из приведенных там примеров мне не подходит, готового решения нет. Было необходимо, чтобы программа могла отправить файл, а так же чтобы тема и тело письма были написаны русским текстом. Т.е получалось, что мне нужно было решить две проблемы, отправка файла и русский текст в письме. Их нужно было решать и как можно скорее.
Решились они многочасовым «гуглением» и собиранием по кусочкам из всего, что только можно.

Привожу рабочий исходник того, что у меня получилось.
//---------------------------------------------------------------------------
#include <vcl.h>
#include <IdText.hpp> // чтобы работал TIdText
#pragma hdrstop

#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "IdBaseComponent"
#pragma link "IdComponent"
#pragma link "IdExplicitTLSClientServerBase"
#pragma link "IdMessage"
#pragma link "IdMessageClient"
#pragma link "IdSMTP"
#pragma link "IdSMTPBase"
#pragma link "IdTCPClient"
#pragma link "IdTCPConnection"
#pragma resource "*.dfm"

#pragma link "crypt32.lib" // чтобы работал base64
#include "IdAttachmentFile.hpp" // чтобы работал TIdAttachmentFile

TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//--Base64-------------------------------------------------------------------
AnsiString Base64Encode(AnsiString s)
{
DWORD sz;
AnsiString res;
CryptBinaryToString((unsigned char*)s.c_str(), s.Length(), CRYPT_STRING_BASE64, NULL, &sz);
char *r;
r = (char*)GlobalAlloc(GPTR, sz);
CryptBinaryToString((unsigned char*)s.c_str(), s.Length(), CRYPT_STRING_BASE64, r, &sz);
res = AnsiString( r );
GlobalFree( r );
res = res.Delete(sz-1, 2);
return res;
}
AnsiString Base64Decode(AnsiString s)
{
DWORD sz;
AnsiString res;

CryptStringToBinary(s.c_str(), s.Length(), CRYPT_STRING_BASE64, NULL, &sz, NULL, NULL);
char *r;
r = (char*)GlobalAlloc(GPTR, sz);
CryptStringToBinary(s.c_str(), s.Length(), CRYPT_STRING_BASE64, r, &sz, NULL, NULL);
res = AnsiString( r );
res.SetLength(sz);
GlobalFree( r );
return res;
}
//---------------------------------------------------------------------------
void __fastcall TForm2::ButtonClick(TObject *Sender)
{
IdSMTP->Disconnect();
//****Авторизация****
IdSMTP->Host="smtp.bank.ru";
IdSMTP->Username="user@bank.ru";
IdSMTP->Password="ahgk*3iHFAJgal";
IdSMTP->Port=25;
IdSMTP->MailAgent="BankMailSender";

IdSMTP->UseTLS=utNoTLSSupport;
IdSMTP->AuthType=satDefault;
IdSMTP->ConnectTimeout=10000;

//****Адреса****
IdMessage->Clear();
IdMessage->OnInitializeISO=IdMessageInitializeISO;
IdMessage->From->Address="user@bank.ru";
AnsiString name="Банк";
IdMessage->From->Name="=?windows-1251?B?"+Base64Encode(name)+"?=";
IdMessage->ReplyTo->Clear();
IdMessage->ReplyTo->EMailAddresses="recipient@bank.ru";
IdMessage->Recipients->EMailAddresses="recipient@bank.com";
IdMessage->ReceiptRecipient->Text="";

IdMessage->CharSet="windows-1251";
AnsiString subj="Русский текст темы";
AnsiString att="c:\\test.txt";
AnsiString body="Русский текст письма";
IdMessage->Subject="=?windows-1251?B?"+Base64Encode(subj)+"?=";

IdMessage->ContentType="multipart/mixed";
IdMessage->Encoding=meMIME;

if (att !="")
{

//****Вложение****
TIdAttachmentFile *attachment = new TIdAttachmentFile(IdMessage->MessageParts, att);

attachment->ContentTransfer="base64";
attachment->ContentDisposition = "attachment";
attachment->ContentType="application/octet-stream;";
attachment->FileName="=?windows-1251?B?"+Base64Encode(ExtractFileName(att))+"?=";;

TIdText *TextPart = new TIdText(IdMessage->MessageParts, NULL);
TextPart->ContentType="text/plain";
TextPart->ContentTransfer="base64";
TextPart->CharSet="windows-1251";

TextPart->Body->Add(body);
TextPart->ParentPart=-1;
}
else
{
IdMessage->ContentType="text/plain";
IdMessage->Body->Add("=?windows-1251?B?"+Base64Encode(body)+"?=");
}
IdSMTP->Connect();
try
{
IdSMTP->Send(IdMessage);
}
__finally
{
IdSMTP->Disconnect();
}
}
//---------------------------------------------------------------------------
void __fastcall TForm2::IdMessageInitializeISO(wchar_t &VHeaderEncoding, UnicodeString &VCharSet)

{
VCharSet="windows-1251";
}
//---------------------------------------------------------------------------

Комментарии к коду, я думаю, излишни, т.к он и без того очень прост в понимании.

Надеюсь, что мои старания кому-нибудь, да пригодятся.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.