(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

Самый простой способ автоматической настройки профиля почты в вашем приложении Delphi

Старенький пост из черновиков. Решил опубликовать, немного  обновив информацию, т.к. с момента выхода Delphi XE2 (когда начинал писать этот пост) времени прошло довольно много и часть информации устарела. На самом деле способов автоматической настройки профиля почты как в Delphi, так и где угодно не так уж и много и кратко я расскажу о них, а самый, на мой взгляд, простой - рассмотрю по-подробнее. Вполне возможно, что вы его реализуете в своих приложениях.

Практически каждый серьезный почтовый клиент имеет в своем составе полезную функцию автоматической настройки профиля почты. Эта функция очень сильно упрощает жизнь рядовым пользователям, которых в дрожь бросает от подсказок типа "Введите номер порта" или "Укажите сервер исходящей почты (SMTP)". С автоматической настройкой все гораздо проще - задал адрес почтового ящика, нажал одну кнопку и всё - все настройки определит программа. Другое дело, что автоматический поиск настроек может не дать результатов и придётся всё-таки пугать пользователя, но это уже другой момент.

Как это работает у других?

В самых общих чертах автоматический поиск настроек аккаунта почты у популярных почтовиков, типа ThunderBird, Outlook, The Bat и т.д. работает следующим образом:

  1. Поиск настроек в файлах конфигурации на жестком диске. Довольно часто почтовики "таскают" с собой файлы с описанием настроек большинства популярных почтовых серверов. Например, тот же ThunderBird хранит настройки в файлах в директории  tb-install-dir/isp/
  2. Если настройки не найдены, то почтовый клиент начинает проверять MX-записи в DNS. Если записи найдены, то клиент пробует использовать их для настройки аккаунта, используя для этого два способа:
    1. "Вырезает" из записи типа "mx1.mail.hoster.com" домен "hoster.com" и снова ищет настройки в конфигурационных файлах как в п.1. или же использует открытые базы данных по настройкам почтовых аккаунтов в Сети.
    2. "Угадывает" номера портов SMTP, POP3, IMAP для хоста, найденного в DNS. Например, вместо  pop3.mail.ru  может выдаться  mxs.mail.ru  и такая настройка тоже будет работать.
  3. Чистое "гадание":
    1. Из адреса почты вырезается домен, например "example.com"
    2. Берутся самые распространенные названия почтовых серверов, например "mail.", "pop3.", "smtp.", "imap." и т.д.
    3. Берутся возможные стандартные номера портов: 465, 995, 993, 25, 110, 143, 587, 585
    4. и начинается "гадание на кофейной гуще" - пробуем соединиться с  mail.example.com  по порту  465 . Если соединились, то значит сервер использует для SMTP SSL, если не удалось соединиться, то берем следующий порт, снова пробуем соединиться и т.д. до тех пор пока не будут найдены настройки или же список адресов и портов не закончится.
  4. Еще один способ автоматического поиска настроек почтового аккаунта - использование протокола AutoDiscover для Microsoft Exchange, но это отдельная тема отдельного поста про Microsoft"овские протоколы и их работу. В частности, этот способ активно использует Outlook.

Это в самых общих чертах о том, как почтовыми клиентами ищутся настройки почтовых аккаунтов. Естественно, что каждый почтовый клиент имеет свои какие-то фичи в этом вопросе, но общий алгоритм у всех один - сначала пробуем найти настройки "культурно" через DNS, файлы конфигурации и т.д. и только после этого начинаем угадывать, перебирать варианты хостов и т.д.

Если вам не требуется реализовывать в своем приложении Delphi навороченные алгоритмы автоматического поиска настроек почты, то самым простым и лёгким в исполнении способом будет, конечно же либо использование своих файлов конфигурации, или же, не на много сложнее - использование открытых баз данных по настройкам для различных серверов. И именно о такой базе и работе с ней пойдёт речь далее.

Использование ISPDB в Delphi

Что такое ISPDB?

ISPDB - это центральная база данных, которая в настоящий момент принадлежит Mozilla Messaging, но может быть использована любым клиентом. Эта база содержит настройки самых популярных (и не очень) почтовых серверов. Настройки каждого сервера находятся в отдельном xml-файле, что позволяет довольно быстро получать необходимую информацию из БД с минимальными затратами интернет-трафика.

ISPBD расположена по адресу: https://autoconfig.thunderbird.net/v1.1/

Чтобы воспользоваться ISPDB нам достаточно выполнить такие простые шаги:

  1. подставить в URL базы имя домена, например, так https://autoconfig.thunderbird.net/v1.1/example.com
  2. отправить GET-запрос на полученный URL (для этого можно воспользоваться, например, Indy или Synapse)
  3. если в ответ получили код 404, то поиск в базе результатов не дал. Если же код ответа 200, то в теле ответа будет содержаться простой XML-файл, содержащий все настройки сервера. Например, для  mail.ru  этот файл выглядит вот так. Всё, что нам нужно - это правильно распарсить этот XML и выдать полученные настройки пользователю.

Реализуем этот простой алгоритм в Delphi. Во избежания всяческих недоразумений, касаемо компиляции исходного кода, представленного ниже в статье, обращу ваше внимание на следующие моменты:

Для работы, на данный момент, я использую только Delphi XE7 (других версий у меня под рукой нет)
Для работы с сетевыми протоколами я использую библиотеку Synapse. Вы же можете легко переписать код под использование той же Indy или ICS.
Теперь перейдем к работе над нашей программкой для автоматического определения настроек профиля почты в Delphi.

Выглядеть наше приложение будет вот так:

ISPDB

Работать оно будет следующим образом:

  1. Пользователь задает адрес почты и жмет "Найти настройки"
  2. Программа отправляет запрос в ISPDB
  3. Если код ответа будет 200, то программа разбирает полученный ответ и сохраняет настройки почты в своем списке
  4. Если код ответа равен 404, то программа запрашивает MX-записи для домена
  5. Если MX-записи получены, то берется первая из них и определяется домен так же, как это делает тот же ThunderBird, т.е. из адреса mx1.anyhost.example.com вырезаем только example.com
  6. Для полученного в п.5 домена пробуем повторить операцию запроса, т.е. повторяем п.п. 2 и 3.
  7. Если и после этого настройки не будут найдены, то считаем, что в ISPDB нет необходимых настроек.

О том как разобрать XML-файл любой сложности в Delphi я рассказывать здесь уже не буду, так как примеров в блоге более, чем достаточно. Скажу только, что для разбора XML я буду использовать только то, что есть в самой Delphi "из коробки".  Для хранения в программе настроек почтового сервера я буду использовать следующий класс:

TServerType = (stIMAP, stPOP, stSMTP); TSocketType = (sSSL, sSTARTTLS, sPlain); TUserName = (unAddress, unLocalPart, unDomain); TPassType = (ptClearText, ptCRAMMD5, ptOther);   TServerOptions = class private FServerType: TServerType; FSocketType: TSocketType; FPort: cardinal; FHostName: string; FUserName: TUserName; FAuthentication: TPassType; public constructor Create(AServerType: TServerType; ASocketType: TSocketType; APort: cardinal; AHostName: string; AUserName: TUserName; AAuthentication: TPassType); destructor Destroy; override; property ServerType: TServerType read FServerType; property SocketType: TSocketType read FSocketType; property Port: cardinal read FPort; property HostName: string read FHostName; property UserName: TUserName read FUserName; property Authentication: TPassType read FAuthentication; end;

Все поля класса соответствуют узлам XML-документа о содержимом которого Вы можете почитать вот на этой странице wiki ThunderBird. На этой страничке расписан формат конфигурационного файла, но он на 100% соответствует содержимому в ISPDB.

Класс для работы с ISPDB будет выглядеть следующим образом:

uses Classes, SysUtils, Generics.Collections, httpsend, dnssend, ssl_openssl, Xml.XMLDoc, Xml.XMLIntf;   TISPDB = class private FServers: TObjectList; function GET(const URL: string; AResponse: TStringStream): integer; function MX(const AEmail: string; AResponse: TStringList):boolean; procedure Parse(AXMLResponse: TStringStream); public constructor Create; destructor Destroy; override; function GetDomain(const AEmail: string): string; function FindOptions(const AEmail: string): boolean; function FindServer(AServerType: TServerType; ASocketType: TSocketType):TServerOptions; property Servers: TObjectList read FServers; end;

Функция GET отправляет HTTP-запрос в базу и получает в результат код ответа сервера:

function TISPDB.GET(const URL: string; AResponse: TStringStream): integer; var HTTP: THTTPSend; begin HTTP := THTTPSend.Create; try if HTTP.HTTPMethod('GET', URL) then AResponse.LoadFromStream(HTTP.Document); Result := HTTP.ResultCode; finally HTTP.Free; end; end;

Функция MX получает MX-записи из DNS:

const cDefaultDNS = '8.8.8.8';   function TISPDB.MX(const AEmail: string; AResponse: TStringList): boolean; begin Result:=GetMailServers(cDefaultDNS,GetDomain(AEmail),AResponse); end;

Процедура Parse разбирает XML-документ и помещает сведения о настройках серверов в список:

procedure TISPDB.Parse(AXMLResponse: TStringStream); const cServerNodes: array [0 .. 4] of string = ('hostname', 'port', 'socketType', 'username', 'authentication'); var XMLDoc: IXMLDocument; Node, ServerNode: IXMLNode; ServerStr: string; ServerType: TServerType; SocketType: TSocketType; Port: cardinal; HostName: string; UserName: TUserName; Authentication: TPassType; begin if not Assigned(AXMLResponse) then raise Exception.Create(rsEmptyXML);   XMLDoc := TXMLDocument.Create(nil); try XMLDoc.LoadFromStream(AXMLResponse); Node := XMLDoc.DocumentElement.ChildNodes.FindNode('emailProvider'); if Assigned(Node) then Node := Node.ChildNodes.First; while Assigned(Node) do begin if SameText(Node.NodeName, 'incomingServer') or SameText(Node.NodeName, 'outgoingServer') then begin ServerStr := Node.Attributes['type']; // определяем тип сервера if SameText(ServerStr, 'imap') then ServerType := TServerType.stIMAP else if SameText(ServerStr, 'pop3') then ServerType := TServerType.stPOP else ServerType := TServerType.stSMTP; // читаем настройки сервера ServerNode := Node.ChildNodes.First; while Assigned(ServerNode) do begin case AnsiIndexStr(ServerNode.NodeName, cServerNodes) of 0: HostName := ServerNode.Text; // hostname 1: Port := StrToInt(ServerNode.Text); // port 2: begin // socketType if SameText(ServerNode.Text, 'SSL') then SocketType := TSocketType.sSSL else if SameText(ServerNode.Text, 'STARTTLS') then SocketType := TSocketType.sSTARTTLS else SocketType := TSocketType.sPlain; end; 3:begin // username if SameText(ServerNode.Text, '%EMAILADDRESS%') then UserName := unAddress else UserName := unLocalPart; end; 4:begin // authentication if SameText(ServerNode.Text, 'password-cleartext') then Authentication:=ptClearText else if SameText(ServerNode.Text, 'password-encrypted') then Authentication:=ptCRAMMD5 else Authentication:=ptOther; end; end; ServerNode := ServerNode.NextSibling; end; FServers.Add(TServerOptions.Create(ServerType,SocketType,Port,HostName,UserName,Authentication)); end; Node := Node.NextSibling; end; finally XMLDoc := nil; end; end;

Основным методом класса является функция FindOptions, которая работает так как было описано выше в алгоритме, т.е. вначале пробуем получить настройки из ISPDB по домену из адреса почты, а затем - из MX-записи:

function TISPDB.FindOptions(const AEmail: string): boolean; var AStream: TStringStream; AMX: TStringList; HTTPResult: integer; Str: TStringDynArray; Domain: string; begin FServers.Clear;   Domain:=GetDomain(AEmail); if Domain.IsEmpty then raise Exception.Create(rsWrongEmailAddress);   AStream:=TStringStream.Create; try HTTPResult:=GET(cBaseURL+Domain,AStream); Result:=HTTPResult=200; if Result then Parse(AStream) else begin AMX:=TStringList.Create; try if MX(AEmail, AMX) then begin Str:=SplitString(AMX[0],'.'); AStream.Clear; HTTPResult:=GET(cBaseURL+LowerCase(Str[High(Str)-1]+'.'+Str[High(Str)]),AStream); Result:=HTTPResult=200; if Result then Parse(AStream) end; finally AMX.Free; end; end; finally AStream.Free end; end;

Это ключевые методы класса, которые Вы, как я уже написал выше, можете переделывать как угодно под использование собственных библиотек для работы с XML и сетевыми протоколами.
Теперь, чтобы воспользоваться разработанным классом, достаточно выполнить всего несколько действий:

procedure TForm1.FormCreate(Sender: TObject); begin ISPDB:=TISPDB.Create; end;   procedure TForm1.FormDestroy(Sender: TObject); begin ISPDB.Free; end;   procedure TForm1.Button1Click(Sender: TObject); begin if ISPDB.FindOptions(edMail.Text) then begin StatusBar1.Panels[1].Text:=ISPDB.Servers.Count.ToString; ShowMessage('Найдены настройки почтового аккаунта'#13#10'Выберите желаемый протокол и тип соединения в списках ниже'); end else begin StatusBar1.Panels[1].Text:='0'; ShowMessage('Настроек почтового аккаунта не найдено в ISPDB'); end; end;

Результат работы приложения на скрине ниже:
ISPDB application

Собственно, более простого способа автоматического получения настроек почты в Delphi, по-моему, нет. Остается только выложить исходник проекта.



 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 13.08.2015 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Enterprise Connectors (1 Year term)
Delphi Professional Named User
Quest Software. Toad for Oracle Development Suite
Quest Software. TOAD Xpert Edition
Quest Software. Toad for SQL Server Development Suite
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
СУБД Oracle "с нуля"
Corel DRAW - от идеи до реализации
Новости мира 3D-ускорителей
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100