home *** CD-ROM | disk | FTP | other *** search
- {*****************************************************************************
- *
- * MailParser.pas - E-mail Parser (22-July-1998)
- *
- * Copyright (c) 1998-99 Michael Haller
- *
- * Author: Michael Haller
- * E-mail: michael@discountdrive.com
- * Homepage: http://www.discountdrive.com/sunrise
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation;
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- *----------------------------------------------------------------------------
- *
- * Revision history:
- *
- * DATE REV DESCRIPTION
- * ----------- --- ----------------------------------------------------------
- *
- *****************************************************************************}
-
- unit MailParser;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- BASE64Sup, DateSup, ParserSup;
-
- type
- TMsgType = (mtText, mtHtml, mtRich);
-
- TEMail = class(TObject)
- private
- public
- ToReceiver, CC, BCC: TStringList;
- Fields, FieldValues: TStringList;
- Subject, Keywords, Priority, From: String;
- ADate, ATime: TDateTime;
- UseMime10: Boolean;
- ContentType, ContentEncoding: String;
- MsgType: TMsgType;
- constructor Create;
- destructor Destroy; override;
- procedure GetMailHeader(var SL: TStringList);
- procedure ParseMail(Filename: String; OnlyHeader: Boolean);
- procedure CompileMsgFileOnDisk(Filename: String);
- end;
-
- implementation
-
- uses
- Main, PXStuff;
-
- var
- F, G: Text;
-
- constructor TEMail.Create;
- begin
- inherited Create;
- ToReceiver := TStringList.Create;
- CC := TStringList.Create;
- BCC := TStringList.Create;
- Fields := TStringList.Create;
- FieldValues := TStringList.Create;
- end;
-
- destructor TEMail.Destroy;
- begin
- ToReceiver.Free;
- CC.Free;
- BCC.Free;
- Fields.Free;
- FieldValues.Free;
- inherited Destroy;
- end;
-
- procedure TEMail.GetMailHeader(var SL: TStringList);
- var
- I: Integer;
- S1, S2: String;
- begin
- try
- ToReceiver.Clear;
- CC.Clear;
- BCC.Clear;
- Fields.Clear;
- FieldValues.Clear;
- From := '';
- Priority := '';
- Subject := '';
- Keywords := '';
- ADate := Date;
- ATime := Time;
- UseMIME10 := False;
- ContentEncoding := '7Bit';
- ContentType := 'text/plain';
- MsgType := StandardMsgType;
- MakeFields(SL, True);
- for I := 0 to SL.Count-1 do begin
- GetFieldArguments(SL.Strings[I], S1, S2);
- if LowerCase(S1) = 'from' then From := SkipChar(S2, '"') else
- if LowerCase(S1) = 'subject' then Subject := S2 else
- if LowerCase(S1) = 'to' then CommataStringToStringList(S2, ToReceiver) else
- if LowerCase(S1) = 'cc' then CommataStringToStringList(S2, CC) else
- if LowerCase(S1) = 'bcc' then CommataStringToStringList(S2, BCC) else
- if LowerCase(S1) = 'date' then MailTimeToDateTime(S2, ADate, ATime) else
- if LowerCase(S1) = 'keywords' then Keywords := S2 else
- if LowerCase(S1) = 'priority' then Priority := S2 else
- if (LowerCase(S1) = 'mime-version') and (LowerCase(S2) = '1.0') then UseMime10 := True else
- if LowerCase(S1) = 'content-type' then ContentType := S2 else
- if LowerCase(S1) = 'content-transfer-encoding' then ContentEncoding := S2 else
- begin {else}
- Fields.Add(S1);
- FieldValues.Add(S2);
- end;
- end;
- // proof the value of some 'special' fields
- if (LowerCase(Priority) <> 'low') and
- (LowerCase(Priority) <> 'normal') and
- (LowerCase(Priority) <> 'high') then Priority := 'Normal';
- except end;
- end;
-
- procedure TEMail.ParseMail(Filename: String; OnlyHeader: Boolean);
- var
- S, T, S1, S2, CntType, CntEncoding: String;
- SL: TStringList;
- I: Integer;
- BoundarayExists: Boolean;
- begin
- try
- AssignFile(F, Filename);
- Reset(F);
- SL := TStringList.Create;
- //Load mail header
- ReadLn(F, S);
- while S <> '' do begin // until CRLF
- SL.Add(S);
- ReadLn(F, S); // fetch new line
- end;
- GetMailHeader(SL);
- if OnlyHeader then begin
- CloseFile(F);
- Exit;
- end;
-
- SL.Clear;
- BoundarayExists := FAlse;
- if UseMIME10 = True then begin
- S := LowerCase(GetContentType('', ContentType));
-
- if S = 'multipart/mixed' then begin
- T := '--'+GetContentType('boundary', ContentType);
- T := SkipChar(T, '"');
- CntType := '';
- CntEncoding := '';
- while not EoF(F) do begin
- ReadLn(F, S);
- if S = T then begin
- // save previous Boundary Block
- if BoundarayExists then SaveMIMEToFile(SL, CntType, CntEncoding);
- // Load new boundary header
- BoundarayExists := True;
- SL.Clear;
- ReadLn(F, S);
- while S <> '' do begin
- SL.Add(S);
- ReadLn(F, S);
- end;
- MakeFields(SL, True);
- for I := 0 to SL.Count-1 do begin
- GetFieldArguments(SL.Strings[I], S1, S2);
- if LowerCase(S1) = 'content-type' then CntType := S2;
- if LowerCase(S1) = 'content-transfer-encoding' then CntEncoding := S2;
- end;
- SL.Clear;
- end else
- if S = T+'--' then begin
- if (CntEncoding <> '') and (CntType <> '') then
- SaveMIMEToFile(SL, CntType, CntEncoding);
- // End of mail
- CloseFile(F);
- SL.Free;
- Exit;
- end else
- SL.Add(S);
- end;
- end else begin
- while not EoF(F) do begin
- ReadLn(F, S);
- SL.Add(S);
- end;
- SaveMIMEToFile(SL, ContentType, ContentEncoding);
- end;
-
- end;
-
- if UseMIME10 = False then begin
- MsgType := mtText;
- AssignFile(G, sTempMessageFile);
- Rewrite(G);
- while not EoF(F) do begin
- ReadLn(F, S);
- WriteLn(G, S);
- end;
- CloseFile(G);
- end;
-
- CloseFile(F);
-
- except end;
- end;
-
- procedure TEMail.CompileMsgFileOnDisk(Filename: String);
- var
- S, S1: String;
- I, Found: Integer;
- B: Byte;
- SearchRec: TSearchRec;
- begin
- AssignFile(F, Filename);
- Rewrite(F);
- // Header
- S := 'From: '+SetMIMEHeaderField(From);
- WriteLn(F, BreakString(S));
- S := 'To: '+StringListToCommataString(ToReceiver, True);
- WriteLn(F, BreakString(S));
- S := StringListToCommataString(CC, True);
- if S <> '' then begin S := 'CC: '+S; WriteLn(F, BreakString(S)); end;
- S := StringListToCommataString(BCC, True);
- if S <> '' then begin S := 'BCC: '+S; WriteLn(F, BreakString(S)); end;
- DateTimeToMailTime(S, ADate, ATime);
- S := 'Date: '+S;
- WriteLn(F, BreakString(S));
- S := Subject;
- if S <> '' then begin S := 'Subject: '+SetMIMEHeaderField(S); WriteLn(F, BreakString(S)); end;
- S := Keywords;
- if S <> '' then begin S := 'Keywords: '+SetMIMEHeaderField(S); WriteLn(F, BreakString(S)); end;
- S := Priority;
- if S <> '' then begin S := 'Priority: '+SetMIMEHeaderField(S); WriteLn(F, BreakString(S)); end;
- for I := 0 to Fields.Count-1 do
- if Fields.Strings[I] <> '' then begin
- S := Fields.Strings[I];
- if LowerCase(S) <> 'x-mailer' then begin
- S := S+': '+SetMIMEHeaderField(FieldValues.Strings[I]);
- WriteLn(F, BreakString(S));
- end;
- end;
- WriteLn(F, BreakString('X-mailer: '+sXMailer));
- WriteLn(F, BreakString('MIME-Version: 1.0'));
- WriteLn(F, BreakString('Content-type: multipart/mixed; boundary=-----Phoenix-Boundary-07081998-'));
- WriteLn(F, '');
- //Message text
- if FileExists(sTempMessageFile) then begin
- WriteLn(F, '-------Phoenix-Boundary-07081998-');
- if MsgType = mtText then
- WriteLn(F, 'Content-type: text/plain; charset=ISO-8859-1');
- if MsgType = mtRich then
- WriteLn(F, 'Content-type: text/richtext; charset=ISO-8859-1');
- if MsgType = mtHtml then
- WriteLn(F, 'Content-type: text/html; charset=ISO-8859-1');
- WriteLn(F, 'Content-transfer-encoding: Quoted-printable');
- WriteLn(F, '');
- AttachFileToTextfile(F, sTempMessageFile, 0);
- WriteLn(F, '');
- end;
- //Attachments
- Found := FindFirst(sTemporaryFolder+'*.*', faReadOnly+faArchive+faHidden+faSysFile, SearchRec);
- while Found = 0 do begin
- if (sTemporaryFolder+SearchRec.Name <> sTempMessageFile) then begin
- GetMIMEType(SearchRec.Name, S, S1, B);
- WriteLn(F, '-------Phoenix-Boundary-07081998-');
- WriteLn(F, 'Content-type: '+S);
- WriteLn(F, 'Content-transfer-encoding: '+S1);
- WriteLn(F, '');
- AttachFileToTextfile(F, sTemporaryFolder+SearchRec.Name, B);
- WriteLn(F, '');
- end;
- Found := FindNext(SearchRec);
- end;
- FindClose(SearchRec);
- //End header
- WriteLn(F, '-------Phoenix-Boundary-07081998---');
- WriteLn(F, '');
- CloseFile(F);
- end;
-
- end.
-