Solved

Can SMTP and POP3 in Dephi work on Hotmail?

Posted on 2004-04-17
4
359 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 14

Expert Comment

by:DragonSlayer
ID: 10849215
0
 
LVL 11

Accepted Solution

by:
shaneholmes earned 500 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

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
This video discusses moving either the default database or any database to a new volume.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

708 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

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now