Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Can SMTP and POP3 in Dephi work on Hotmail?

Posted on 2004-04-17
4
Medium Priority
?
400 Views
Last Modified: 2010-04-05
I am working on a program to handle incoming and outgoing email. From my previous work, it is certain that I can manage certain email with ISP. For Hotmail, I cannot find any reference for the time being.

So I need to ask if some experts know about this and perhaps some hints for what is need to handle.
0
Comment
Question by:fhtong
  • 2
  • 2
4 Comments
 
LVL 11

Expert Comment

by:shaneholmes
ID: 10849134
Hotmail used to have POP3 and SMTP mail servers.  But those were eliminated when Microsoft
added HTTP support for Hotmail in Outlook Express version 5.

Example,

tool/accounts/add/mail

choose Http as incoming mail server and the Hotmail selection becomes available

http://services.msn.com/svcs/hotmail/httpmail.asp

Shane

0
 
LVL 11

Accepted Solution

by:
shaneholmes earned 2000 total points
ID: 10849233
Here's a component you can use to get your Hotmail. It get's a list of the
Emails. You can download an Email, and delete it.

 wrote a POP3 front-end around it, so one could get Hotmail from
Outlook 2000.


unit HotmailConnection;

(*
 Delphi conversion of Httpmail project:
  http://httpmail.sourceforge.net

 Usage:
var
 Hotmail: THotmail;
 i: Integer;
 MailInfo: TMailInfo;
 szEmailText: string;
 szDeleteMail: string;
begin
 Hotmail := THotmail.Create;
 try
  //authentication information
  Hotmail.Username := 'bgates';
  Hotmail.Password := 'blackthorn';

  //try to connect
  if not Hotmail.Connect then Exit;

  //"bind" the Mail list to the contents of the Inbox
  Hotmail.ParseMailboxInfo(Hotmail.InboxURL);

  //process mail in the inbox
  for i := 0 to Hotmail.Mail.Count-1 do
  begin
   MailInfo := Hotmail.Mail.Items[i] as TMailInfo;

   szEmailText := Hotmail.Retrieve(MailInfo.mUrl);
   ShowMessage(szEmailText);

   //Mail to delete is a CRLF separated string of mail URL's
   szDeleteEmails := szDeleteMails + MailInfo.mUrl + #13#10;
  end;

  //Delete the specified emails from the Inbox
  Hotmail.DeleteMail(szDeleteEmails, Hotmail.InboxURL);
 finally
  Hotmail.Free;
 end;
end;
*)

interface

uses
 MSXML2_TLB, Contnrs, Classes, Variants, SysUtils, ComObj;

type
 TFolderInfo = class(TObject)
 private
  FName: string;
  FUrl: string;
//  FUnread: Integer;
 public
  property Name: string read FName write FName;
  property URL: string  read FURL  write FURL;
//  property UnreadCount: Integer read FUnread write FUnread;
 end;

 TMailInfo = class(TObject)
 public
  mSubject: string;
  mTo: string;
  mFrom: string;
  mDate: TDateTime;
  mLength: Integer;
  mUrl: string;
  mRead: Boolean;
 end;

 THotmail = class(TObject)
 private
  XMLHttp: IServerXMLHTTPRequest;
  XMLDoc: IXMLDOMDocument;

  FRootFolderURL: string;
  FFolderList: TObjectList;
  FMailList: TObjectList;
  FUsername: string;
  FPassword: string;
  FResponseText: string;
  FResponseHeaders: string;
  FHotmailError: string;
  FRequestStatus: Integer;
  FRequestStatusText: string;
  FBaseRefURL: string;

  FAdPaneURL: string;
  FContactsURL: string;
  FInboxURL: string;
  FOutboxURL: string;
  FSentItemsURL: string;
  FTrashURL: string;

  function RetrieveFolderURLs: Boolean;
  procedure ParseFolderInfo;
  function GetAllFolderInfo: string;
  function GetMailInfo(MailboxURL: string): string;

//  function GetFolderInfo(FolderURL: string): string; //depricated

  function HotmailStrToDateTime(const szDateTime: string): TDateTime;
  function ExtractMailName(MailUrl: string): string;
 public
  constructor Create;
  destructor Destroy; override;

  function Connect: Boolean;
  procedure ParseMailboxInfo(MailboxURL: string);

  function RetrieveMail(MailURL: string): string;
  function MoveMail(uMail, SrcFolder, DestFolder: string): string;
  function DeleteMail(MailList: string; Folder: string): Boolean;
  procedure FlagMailRead(ukey, currentfolder: string);
  procedure FlagMailUnread(ukey, currentfolder: string);

  property Folders: TObjectList read FFolderList;
   //List of folders in the system
  property Mail: TObjectList read FMailList;
   //List of mail in a folder after a call to ParseMailboxInfo
  property Username: string read FUsername write FUsername;
  property Password: string read FPassword write FPassword;
   //Authentication Information

  { Folder URLs - will be filled with real URL's after Connecting}
  property AdPaneURL: string read FAdPaneURL;
  property ContactsURL: string read FContactsURL;
  property InboxURL: string read FInboxURL;
  property OutboxURL: string read FOutboxURL;
  property SentItemsURL: string read FSentItemsURL;
  property TrashURL: string read FTrashURL;

  { Status }
  property ResponseText: string read FResponseText;
  property ResponseHeaders: string read FResponseHeaders;
  property HotmailError: string read FHotmailError;
  property Status: Integer read FRequestStatus;
  property StatusText: string read FRequestStatusText;
 end;

implementation

uses DateUtils, StrUtils;

resourcestring
 SHotmailURL = 'http://services.msn.com/svcs/hotmail/httpmail.asp';
  // This is the base URL to access Hotmail services!
 SQueryFolders =
  '<?xml version=''1.0''?>'+
   '<D:propfind xmlns:D=''DAV:''
xmlns:h=''http://schemas.microsoft.com/hotmail/''
xmlns:hm=''urn:schemas:httpmail:''>'+
    '<D:prop>'+
     '<h:adbar/>'+
     '<hm:contacts/>'+
     '<hm:inbox/>'+
     '<hm:outbox/>'+
     '<hm:sendmsg/>'+
     '<hm:sentitems/>'+
     '<hm:deleteditems/>'+
     '<hm:drafts/>'+
     '<hm:msgfolderroot/>'+
     '<h:maxpoll/>'+
     '<h:sig/>'+
    '</D:prop>'+
   '</D:propfind>';
  //XML to return folder info back in the response

 SGetMail = '<?xml version=''1.0''?><D:propfind xmlns:D=''DAV:''
xmlns:hm=''urn:schemas:httpmail:''
xmlns:m=''urn:schemas:mailheader:''><D:prop><D:isfolder/><hm:read/><m:hasatt
achment/><m:to/><m:from/><m:subject/><m:date/><D:getcontentlength/></D:prop>
</D:propfind>';
 SGetFolderInfo = '<?xml version=''1.0''?><D:propfind xmlns:D=''DAV:''
xmlns:hm=''urn:schemas:httpmail:''><D:prop><D:isfolder/><D:displayname/><hm:
special/><D:hassubs/><D:nosubs/><hm:unreadcount/><D:visiblecount/><hm:specia
l/></D:prop></D:propfind>';
  //XML to get info about a folder
 SFlagMailRead = '<?xml version=''1.0''?><D:propertyupdate xmlns:D=''DAV:''
xmlns:hm=''urn:schemas:httpmail:''><D:set><D:prop><hm:read>1</hm:read></D:pr
op></D:set></D:propertyupdate>';
 SFlagMailUnread = '<?xml version=''1.0''?><D:propertyupdate
xmlns:D=''DAV:''
xmlns:hm=''urn:schemas:httpmail:''><D:set><D:prop><hm:read>0</hm:read></D:pr
op></D:set></D:propertyupdate>';
 SMoveMail =
  '<?xml version=''1.0''?>'+#13#10+
  '<D:move xmlns:D=''DAV:''>'+#13#10+
  '<D:target>'+#13#10+
  '</D:target>'+#13#10+
  '</D:move>';

{ THotmail }

function THotmail.Connect: Boolean;
//Connects to Hotmail
begin
 // We issue a PROPFIND verb to get the location of the ROOTFOLDER
 try
  if (Length(FUsername) = 0) then
   XMLHTTP.open('PROPFIND', SHotmailURL, False, EmptyParam, EmptyParam)
  else
   XMLHTTP.open('PROPFIND', SHotmailURL, False, FUserName, FPassword);
 except
  on E:Exception do
  begin
   Result := False;
   FRequestStatusText := E.Message;
   Exit;
  end;
 end;

 XMLHTTP.setRequestHeader('PROPFIND', SQueryFolders);
 XMLHTTP.send(EmptyParam);
 FResponseText := XMLHTTP.ResponseText;
 FResponseHeaders := XMLHTTP.getAllResponseHeaders;
 FHotmailError := XMLHTTP.getResponseHeader('X-Dav-Error');
 FRequestStatus := XMLHTTP.status;
 FRequestStatusText := XMLHTTP.statusText;

 if (FRequestStatus < 200) or (FRequestStatus >= 300) then
 begin
  Result := False;
  Exit;
 end;

 Result := True;

 RetrieveFolderURLs;
 ParseFolderInfo;
end;

constructor THotmail.Create;
begin
 XMLHttp := CreateOleObject('MSXML2.ServerXMLHTTP') as
IServerXMLHTTPRequest;
 XMLDoc := CreateOleObject('MSXML2.DOMDocument') as IXMLDOMDocument;
 FFolderList := TObjectList.Create;
 FMailList := TObjectList.Create;
end;

function THotmail.ExtractMailName(MailUrl: string): string;
{
 Typical Email url is of the form

http://bay2.oe.hotmail.com/cgi-bin/hmdata/bill@hotmail.com/folders/ACTIVE/MS
G1042461136.120

 Strip off everything except the final filename "MSG1042461136.120"
}
var
 i: Integer;
 DelimiterPos: Integer;
begin
 DelimiterPos := -1;
 for i := Length(MailURL) downto 1 do
 begin
  if IsDelimiter('/', MailURL, i) then
  begin
   DelimiterPos := i;
   Break;
  end;
 end;

 if DelimiterPos = -1 then
  Result := MailURL
 else
  Result := Copy(MailURL, DelimiterPos+1, Length(MailURL));
end;

function THotmail.DeleteMail(MailList: string; Folder: string): Boolean;
{Delete the specified Emails from the given folder.
 MailList is a CRLF separated string of Mail URLs}
var
 Doc: IXMLDOMDocument;
 Element: IXMLDOMElement;
 Root: IXMLDOMElement;

 slMails: TStrings;
 i: Integer;
begin
 Doc := CreateOleObject('MSXML2.DOMDocument') as IXMLDOMDocument;
 Doc.loadXML(SMoveMail);
 Root := Doc.documentElement;

 slMails := TStringList.Create;
 try
  slMails.Text := MailList;

  for i := 0 To slMails.Count-1 do
  begin
   Element := Doc.createElement('D:href');
   Element.Text := ExtractMailName(slMails.Strings[i]);
   Root.childNodes[0].appendChild(Element);
  end;

  XMLHTTP.open('BMOVE', Folder, False, EmptyParam, EmptyParam);
  XMLHTTP.setRequestHeader('Destination', FTrashURL);
  XMLHTTP.setRequestHeader('Allow-Rename', 't');
  XMLHTTP.setRequestHeader('Content-Type', 'text/xml');
  XMLHTTP.setRequestHeader('User-Agent', 'Outlook-Express/6.0 (MSIE 6.0;
Windows NT 5.1; .NET CLR 1.0.3705; TmstmpExt)');
  XMLHTTP.send(Doc.xml);
  FResponseText := XMLHTTP.ResponseText;
  FHotmailError := XMLHTTP.getResponseHeader('X-Dav-Error');
  FRequestStatus := XMLHTTP.status;
  FRequestStatusText := XMLHTTP.statusText;
  Result := (FRequestStatus >= 200) and (FRequestStatus <= 299);

  ParseMailboxInfo(Folder);
 finally
  slMails.Free;
 end;
end;

destructor THotmail.Destroy;
begin
 XMLHttp := nil;
 XMLDoc := nil;
 FFolderList.Free;
 FMailList.Free;

 inherited;
end;

procedure THotmail.FlagMailRead(ukey, currentfolder: string);
begin
 XMLHTTP.open('PROPPATCH', ukey, False, EmptyParam, EmptyParam);
 XMLHTTP.send(SFlagMailRead);
 FResponseText := XMLHTTP.ResponseText;
 FHotmailError := XMLHTTP.getResponseHeader('X-Dav-Error');
 ParseMailboxInfo(currentfolder);
end;

procedure THotmail.FlagMailUnread(ukey, currentfolder: string);
begin
 XMLHTTP.open('PROPPATCH', ukey, False, EmptyParam, EmptyParam);
 XMLHTTP.send(SFlagMailUnread);
 FResponseText := XMLHTTP.ResponseText;
 FHotmailError := XMLHTTP.getResponseHeader('X-Dav-Error');
 ParseMailboxInfo(currentfolder);
end;

function THotmail.GetAllFolderInfo: string;
begin
 XMLHTTP.open('PROPFIND', FRootFolderURL, False, EmptyParam, EmptyParam);
 XMLHTTP.send(SGetFolderInfo);
 FResponseHeaders := XMLHTTP.getAllResponseHeaders;
 FResponseText := XMLHTTP.ResponseText;
 FHotmailError := XMLHTTP.getResponseHeader('X-Dav-Error');
 FRequestStatus := XMLHTTP.status;
 FRequestStatusText := XMLHTTP.statusText;
 Result := FResponseText;
end;

function THotmail.GetMailInfo(MailboxURL: string): string;
begin
 XMLHTTP.open('PROPFIND', MailboxURL, False, EmptyParam, EmptyParam);
 XMLHTTP.send(SGetMail);
 FResponseHeaders := XMLHTTP.getAllResponseHeaders;
 FResponseText := XMLHTTP.ResponseText;
 FHotmailError := XMLHTTP.getResponseHeader('X-Dav-Error');
 FRequestStatus := XMLHTTP.status;
 FRequestStatusText := XMLHTTP.statusText;
 Result := FResponseText
end;

function THotmail.HotmailStrToDateTime(
  const szDateTime: string): TDateTime;
{ It uses the ISO standard format
 2003-01-13T08:25:40
 1234 67 91 23 56 89
}
var
 wYear, wMonth, wDay: Word;
 wHour, wMinute, wSecond, wMillisecond: Word;
begin
 wYear :=  StrToIntDef(Copy(szDateTime, 1, 4), 1899);
 wMonth :=  StrToIntDef(Copy(szDateTime, 6, 2), 12);
 wDay :=   StrToIntDef(Copy(szDateTime, 9, 2), 30);

 wHour :=  StrToIntDef(Copy(szDateTime, 12, 2), 0);
 wMinute :=  StrToIntDef(Copy(szDateTime, 15, 2), 0);
 wSecond :=  StrToIntDef(Copy(szDateTime, 18, 2), 0);
 wMillisecond := 0;

 Result := EncodeDateTime(wYear, wMonth, wDay,
   wHour, wMinute, wSecond, wMillisecond);
end;

function THotmail.MoveMail(uMail, SrcFolder, DestFolder: string): string;
//Move's Mail to designated folder"
var
 Doc: IXMLDOMDocument;
 Root: IXMLDOMElement;
 Element: IXMLDOMElement;
begin
 Doc := CreateOleObject('MSXML2.DOMDocument') as IXMLDOMDocument;
 Doc.loadXML(SMoveMail);
 Root := Doc.documentElement;
 Element := Doc.createElement('D:href');
 Element.Text := uMail;
 Root.childNodes[0].appendChild(Element);

 XMLHTTP.open('BMOVE', SrcFolder, False, EmptyParam, EmptyParam);
 XMLHTTP.setRequestHeader('Destination', DestFolder);
 XMLHTTP.setRequestHeader('Content-Type', 'text/xml');
 XMLHTTP.send(Doc.xml);
 Result := XMLHTTP.getAllResponseHeaders;
 FResponseText := XMLHTTP.ResponseText;
 FHotmailError := XMLHTTP.getResponseHeader('X-Dav-Error');
 ParseMailboxInfo(SrcFolder);
end;

procedure THotmail.ParseFolderInfo;
var
 Doc: IXMLDOMDocument;
 Nodelist: IXMLDOMNodeList;
 i: Integer;
 Node: IXMLDOMNode;
 Info: TFolderInfo;
begin
 FFolderList.Clear;

 Doc := CreateOLEObject('MSXML2.DOMDocument') as IXMLDOMDocument;
 Doc.loadXML(GetAllFolderInfo);
 Nodelist := Doc.selectNodes('//D:response');
 for i := 0 to Nodelist.length-1 do
 begin
  Node := Nodelist.Item[i];
  Info := TFolderInfo.Create;

  Info.Url := Node.childNodes[0].text;
  Info.Name := Node.childNodes[1].childNodes[0].childNodes[1].text;
//  Info.UnreadCount :=
StrToInt(Node.childNodes[1].childNodes[0].childNodes[4].text);

  FFolderList.Add(Info);
 end;
end;

procedure THotmail.ParseMailboxInfo(MailboxURL: string);
{Bind the .Mail list to the contents of the specify folder}
var
 Doc: IXMLDOMDocument;
 xNodelist: IXMLDOMNodeList;
 mNodeList: IXMLDOMNodeList;
 i: Integer;
 Node: IXMLDOMNode;
 Info: TMailInfo;
 szDate: string;
 iRead: Integer;
 MailBox: string;
begin
 FMailList.Clear;

 MailBox := GetMailInfo(MailboxURL);

 Doc := CreateOLEObject('MSXML2.DOMDocument') as IXMLDOMDocument;
 Doc.loadXML(MailBox);

 xNodelist := Doc.selectNodes('//D:response');
 mNodeList := Doc.selectNodes('//D:prop');

 try
  for i := 0 To xNodelist.length-1 do
  begin
   Node := xNodelist.Item[i];

   Info := TMailInfo.Create;
   Info.mUrl := Node.childNodes[0].Text;
   Info.mSubject :=
mNodeList.Item[i].selectNodes('//m:subject').Item[i].Text;
   Info.mTo := mNodeList.Item[i].selectNodes('//m:to').Item[i].Text;
   Info.mFrom := mNodeList.Item[i].selectNodes('//m:from').Item[i].Text;
   szDate := mNodeList.Item[i].selectNodes('//m:date').Item[i].Text;
   Info.mDate := HotmailStrToDateTime(szDate);
   Info.mLength :=
StrToIntDef(mNodeList.Item[i].selectNodes('//D:getcontentlength').Item[i].Te
xt, 0);
   iRead :=
StrToInt(mNodeList.Item[i].selectNodes('//hm:read').Item[i].Text);
   Info.mRead := (iRead = 1);
   FMailList.Add(Info);
  end;
 except
 end;
end;

function THotmail.RetrieveMail(MailURL: string): string;
{Retrieve the specified Email as a string}
begin
 XMLHTTP.open('GET', MailURL, False, EmptyParam, EmptyParam);
 XMLHTTP.send(EmptyParam);
 Result := XMLHTTP.responseText;
end;

function THotmail.RetrieveFolderURLs: Boolean;
var
 Element: IXMLDOMElement;
 NodeList: IXMLDOMNodeList;

 node1: IXMLDOMNode;
 node2: IXMLDOMNode;
 node3: IXMLDOMNode;
 node4: IXMLDOMNode;
begin
{
 sometimes the encoding sent by hotmail doesn't get loaded correctly.
 in this case, uncomment the line below to get rid of the encoding.
 FResponseText = ReplaceString(FResponseText, 'encoding=' + #34 +
'Windows-1252' + #34, '', 1, 1);
}
 if not XMLDoc.LoadXML(FResponseText) then
 begin
  Result := False;
  FHotmailError := 'Invalid response from server: '+
    XMLDoc.parseError.reason;
  Exit;
 end;

 if XMLDoc.childNodes.length = 0 then
 begin
  Result := False;
  FHotmailError := 'Invalid response from server (no xml)';
  Exit;
 end;

 Element := XMLDoc.documentElement;
 NodeList := Element.childNodes;
 Node1 := NodeList.Item[0];

 Node2 :=     Node1.childNodes.Item[0];
 FBaseRefURL :=   Node2.text;
 Node3 :=     Node1.childNodes.Item[1];
 Node4 :=     Node3.childNodes.Item[0];
 FAdPaneURL :=    Node4.childNodes.Item[0].text;
 FContactsURL :=   Node4.childNodes.Item[1].text;
 FInboxURL :=    Node4.childNodes.Item[2].text;
 FOutboxURL :=    Node4.childNodes.Item[3].text;
 FSentItemsURL :=   Node4.childNodes.Item[4].text;
 FTrashURL :=    Node4.childNodes.Item[5].text;
 FRootFolderURL :=  Node4.childNodes.Item[6].text;

 Result := True;
end;

(* depricated function
function THotmail.GetFolderInfo(FolderURL: string): string;
begin
 XMLHTTP.open('PROPFIND', FolderURL, False, EmptyParam, EmptyParam);
 XMLHTTP.send(SGetFolderInfo);
 FResponseHeaders := XMLHTTP.getAllResponseHeaders;
 FResponseText := XMLHTTP.ResponseText;
 FHotmailError := XMLHTTP.getResponseHeader('X-Dav-Error');
 FRequestStatus := XMLHTTP.status;
 FRequestStatusText := XMLHTTP.statusText;
 Result := FResponseText;
end;
*)

end.
0
 
LVL 14

Expert Comment

by:DragonSlayer
ID: 10849263
the hotpop3 project above is already a POP3 front-end :-)
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Is your data getting by on basic protection measures? In today’s climate of debilitating malware and ransomware—like WannaCry—that may not be enough. You need to establish more than basics, like a recovery plan that protects both data and endpoints.…
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Suggested Courses

885 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question