git-svn-id: https://svn.code.sf.net/p/synalist/code/trunk@57 7c85be65-684b-0410-a082-b2ed4fbef004
459 lines
13 KiB
ObjectPascal
459 lines
13 KiB
ObjectPascal
{==============================================================================|
|
|
| Project : Delphree - Synapse | 001.007.002 |
|
|
|==============================================================================|
|
|
| Content: MIME message object |
|
|
|==============================================================================|
|
|
| The contents of this file are Subject to the Mozilla Public License Ver. 1.1 |
|
|
| (the "License"); you may not use this file except in compliance with the |
|
|
| License. You may obtain a copy of the License at http://www.mozilla.org/MPL/ |
|
|
| |
|
|
| Software distributed under the License is distributed on an "AS IS" basis, |
|
|
| WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for |
|
|
| the specific language governing rights and limitations under the License. |
|
|
|==============================================================================|
|
|
| The Original Code is Synapse Delphi Library. |
|
|
|==============================================================================|
|
|
| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
|
|
| Portions created by Lukas Gebauer are Copyright (c)2000,2001. |
|
|
| All Rights Reserved. |
|
|
|==============================================================================|
|
|
| Contributor(s): |
|
|
|==============================================================================|
|
|
| History: see HISTORY.HTM From distribution package |
|
|
| (Found at URL: http://www.ararat.cz/synapse/) |
|
|
|==============================================================================}
|
|
|
|
{$WEAKPACKAGEUNIT ON}
|
|
|
|
unit MIMEmess;
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils,
|
|
MIMEpart, SynaChar, SynaUtil, MIMEinLn;
|
|
|
|
type
|
|
TMessHeader = class(TObject)
|
|
private
|
|
FFrom: string;
|
|
FToList: TStringList;
|
|
FCCList: TStringList;
|
|
FSubject: string;
|
|
FOrganization: string;
|
|
FCustomHeaders: TStringList;
|
|
FDate: TDateTime;
|
|
FXMailer: string;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Clear;
|
|
procedure EncodeHeaders(const Value: TStringList);
|
|
procedure DecodeHeaders(const Value: TStringList);
|
|
function FindHeader(Value: string): string;
|
|
procedure FindHeaderList(Value: string; const HeaderList: TStringList);
|
|
published
|
|
property From: string read FFrom Write FFrom;
|
|
property ToList: TStringList read FToList;
|
|
property CCList: TStringList read FCCList;
|
|
property Subject: string read FSubject Write FSubject;
|
|
property Organization: string read FOrganization Write FOrganization;
|
|
property CustomHeaders: TStringList read FCustomHeaders;
|
|
property Date: TDateTime read FDate Write FDate;
|
|
property XMailer: string read FXMailer Write FXMailer;
|
|
end;
|
|
|
|
TMimeMess = class(TObject)
|
|
private
|
|
FPartList: TList;
|
|
FLines: TStringList;
|
|
FHeader: TMessHeader;
|
|
FMultipartType: string;
|
|
public
|
|
constructor Create;
|
|
destructor Destroy; override;
|
|
procedure Clear;
|
|
function AddPart: Integer;
|
|
procedure AddPartText(const Value: TStringList);
|
|
procedure AddPartHTML(const Value: TStringList);
|
|
procedure AddPartHTMLBinary(Value, Cid: string);
|
|
procedure AddPartBinary(Value: string);
|
|
procedure EncodeMessage;
|
|
procedure FinalizeHeaders;
|
|
procedure ParseHeaders;
|
|
procedure DecodeMessage;
|
|
published
|
|
property PartList: TList read FPartList;
|
|
property Lines: TStringList read FLines;
|
|
property Header: TMessHeader read FHeader;
|
|
property MultipartType: string read FMultipartType Write FMultipartType;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{==============================================================================}
|
|
|
|
constructor TMessHeader.Create;
|
|
begin
|
|
inherited Create;
|
|
FToList := TStringList.Create;
|
|
FCCList := TStringList.Create;
|
|
FCustomHeaders := TStringList.Create;
|
|
end;
|
|
|
|
destructor TMessHeader.Destroy;
|
|
begin
|
|
FCustomHeaders.Free;
|
|
FCCList.Free;
|
|
FToList.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
procedure TMessHeader.Clear;
|
|
begin
|
|
FFrom := '';
|
|
FToList.Clear;
|
|
FCCList.Clear;
|
|
FSubject := '';
|
|
FOrganization := '';
|
|
FCustomHeaders.Clear;
|
|
FDate := 0;
|
|
FXMailer := '';
|
|
end;
|
|
|
|
procedure TMessHeader.EncodeHeaders(const Value: TStringList);
|
|
var
|
|
n: Integer;
|
|
s: string;
|
|
begin
|
|
if FDate = 0 then
|
|
FDate := Now;
|
|
for n := FCustomHeaders.Count - 1 downto 0 do
|
|
if FCustomHeaders[n] <> '' then
|
|
Value.Insert(0, FCustomHeaders[n]);
|
|
if FXMailer = '' then
|
|
Value.Insert(0, 'x-mailer: Synapse - Delphi & Kylix TCP/IP library by Lukas Gebauer')
|
|
else
|
|
Value.Insert(0, 'x-mailer: ' + FXMailer);
|
|
Value.Insert(0, 'MIME-Version: 1.0 (produced by Synapse)');
|
|
if FOrganization <> '' then
|
|
Value.Insert(0, 'Organization: ' + InlineCode(FOrganization));
|
|
s := '';
|
|
for n := 0 to FCCList.Count - 1 do
|
|
if s = '' then
|
|
s := InlineEmail(FCCList[n])
|
|
else
|
|
s := s + ' , ' + InlineEmail(FCCList[n]);
|
|
if s <> '' then
|
|
Value.Insert(0, 'CC: ' + s);
|
|
Value.Insert(0, 'Date: ' + Rfc822DateTime(FDate));
|
|
if FSubject <> '' then
|
|
Value.Insert(0, 'Subject: ' + InlineCode(FSubject));
|
|
s := '';
|
|
for n := 0 to FToList.Count - 1 do
|
|
if s = '' then
|
|
s := InlineEmail(FToList[n])
|
|
else
|
|
s := s + ' , ' + InlineEmail(FToList[n]);
|
|
if s <> '' then
|
|
Value.Insert(0, 'To: ' + s);
|
|
Value.Insert(0, 'From: ' + InlineEmail(FFrom));
|
|
end;
|
|
|
|
procedure TMessHeader.DecodeHeaders(const Value: TStringList);
|
|
var
|
|
s, t: string;
|
|
x: Integer;
|
|
cp: TMimeChar;
|
|
begin
|
|
cp := GetCurCP;
|
|
Clear;
|
|
x := 0;
|
|
while Value.Count > x do
|
|
begin
|
|
s := NormalizeHeader(Value, x);
|
|
if s = '' then
|
|
Break;
|
|
if Pos('X-MAILER:', UpperCase(s)) = 1 then
|
|
begin
|
|
FXMailer := SeparateRight(s, ':');
|
|
continue;
|
|
end;
|
|
if Pos('FROM:', UpperCase(s)) = 1 then
|
|
begin
|
|
FFrom := InlineDecode(SeparateRight(s, ':'), cp);
|
|
continue;
|
|
end;
|
|
if Pos('SUBJECT:', UpperCase(s)) = 1 then
|
|
begin
|
|
FSubject := InlineDecode(SeparateRight(s, ':'), cp);
|
|
continue;
|
|
end;
|
|
if Pos('ORGANIZATION:', UpperCase(s)) = 1 then
|
|
begin
|
|
FOrganization := InlineDecode(SeparateRight(s, ':'), cp);
|
|
continue;
|
|
end;
|
|
if Pos('TO:', UpperCase(s)) = 1 then
|
|
begin
|
|
s := SeparateRight(s, ':');
|
|
repeat
|
|
t := InlineDecode(fetch(s, ','), cp);
|
|
if t <> '' then
|
|
FToList.Add(t);
|
|
until s = '';
|
|
continue;
|
|
end;
|
|
if Pos('CC:', UpperCase(s)) = 1 then
|
|
begin
|
|
s := SeparateRight(s, ':');
|
|
repeat
|
|
t := InlineDecode(fetch(s, ','), cp);
|
|
if t <> '' then
|
|
FCCList.Add(t);
|
|
until s = '';
|
|
continue;
|
|
end;
|
|
if Pos('DATE:', UpperCase(s)) = 1 then
|
|
begin
|
|
FDate := DecodeRfcDateTime(SeparateRight(s, ':'));
|
|
continue;
|
|
end;
|
|
FCustomHeaders.Add(s);
|
|
end;
|
|
end;
|
|
|
|
function TMessHeader.FindHeader(Value: string): string;
|
|
var
|
|
n: integer;
|
|
begin
|
|
Result := '';
|
|
for n := 0 to FCustomHeaders.Count - 1 do
|
|
if Pos(Value, FCustomHeaders[n]) = 1 then
|
|
begin
|
|
Result := SeparateRight(FCustomHeaders[n], ':');
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
procedure TMessHeader.FindHeaderList(Value: string; const HeaderList: TStringList);
|
|
var
|
|
n: integer;
|
|
begin
|
|
HeaderList.Clear;
|
|
for n := 0 to FCustomHeaders.Count - 1 do
|
|
if Pos(Value, FCustomHeaders[n]) = 1 then
|
|
begin
|
|
HeaderList.Add(SeparateRight(FCustomHeaders[n], ':'));
|
|
end;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
constructor TMimeMess.Create;
|
|
begin
|
|
inherited Create;
|
|
FPartList := TList.Create;
|
|
FLines := TStringList.Create;
|
|
FHeader := TMessHeader.Create;
|
|
FMultipartType := 'Mixed';
|
|
end;
|
|
|
|
destructor TMimeMess.Destroy;
|
|
begin
|
|
Clear;
|
|
FHeader.Free;
|
|
Lines.Free;
|
|
PartList.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
procedure TMimeMess.Clear;
|
|
var
|
|
n: Integer;
|
|
begin
|
|
FMultipartType := 'Mixed';
|
|
Lines.Clear;
|
|
for n := 0 to FPartList.Count - 1 do
|
|
TMimePart(FPartList[n]).Free;
|
|
FPartList.Clear;
|
|
FHeader.Clear;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
function TMimeMess.AddPart: Integer;
|
|
begin
|
|
Result := FPartList.Add(TMimePart.Create);
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
procedure TMimeMess.AddPartText(const Value: TStringList);
|
|
begin
|
|
with TMimePart(FPartList[AddPart]) do
|
|
begin
|
|
Value.SaveToStream(DecodedLines);
|
|
Primary := 'text';
|
|
Secondary := 'plain';
|
|
Description := 'Message text';
|
|
Disposition := 'inline';
|
|
CharsetCode := IdealCharsetCoding(Value.Text, TargetCharset,
|
|
[ISO_8859_1, ISO_8859_2, ISO_8859_3, ISO_8859_4, ISO_8859_5,
|
|
ISO_8859_6, ISO_8859_7, ISO_8859_8, ISO_8859_9, ISO_8859_10]);
|
|
EncodingCode := ME_QUOTED_PRINTABLE;
|
|
EncodePart;
|
|
end;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
procedure TMimeMess.AddPartHTML(const Value: TStringList);
|
|
begin
|
|
with TMimePart(FPartList[AddPart]) do
|
|
begin
|
|
Value.SaveToStream(DecodedLines);
|
|
Primary := 'text';
|
|
Secondary := 'html';
|
|
Description := 'HTML text';
|
|
Disposition := 'inline';
|
|
CharsetCode := UTF_8;
|
|
EncodingCode := ME_QUOTED_PRINTABLE;
|
|
EncodePart;
|
|
end;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
procedure TMimeMess.AddPartBinary(Value: string);
|
|
var
|
|
s: string;
|
|
begin
|
|
with TMimePart(FPartList[AddPart]) do
|
|
begin
|
|
DecodedLines.LoadFromFile(Value);
|
|
s := ExtractFileName(Value);
|
|
MimeTypeFromExt(s);
|
|
Description := 'Attached file: ' + s;
|
|
Disposition := 'attachment';
|
|
FileName := s;
|
|
EncodingCode := ME_BASE64;
|
|
EncodePart;
|
|
end;
|
|
end;
|
|
|
|
procedure TMimeMess.AddPartHTMLBinary(Value, Cid: string);
|
|
var
|
|
s: string;
|
|
begin
|
|
with TMimePart(FPartList[AddPart]) do
|
|
begin
|
|
DecodedLines.LoadFromFile(Value);
|
|
s := ExtractFileName(Value);
|
|
MimeTypeFromExt(s);
|
|
Description := 'Included file: ' + s;
|
|
Disposition := 'inline';
|
|
ContentID := Cid;
|
|
FileName := s;
|
|
EncodingCode := ME_BASE64;
|
|
EncodePart;
|
|
end;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
procedure TMimeMess.EncodeMessage;
|
|
var
|
|
bound: string;
|
|
n: Integer;
|
|
begin
|
|
FLines.Clear;
|
|
if FPartList.Count = 1 then
|
|
FLines.Assign(TMimePart(FPartList[0]).Lines)
|
|
else
|
|
begin
|
|
bound := GenerateBoundary;
|
|
for n := 0 to FPartList.Count - 1 do
|
|
begin
|
|
FLines.Add('--' + bound);
|
|
FLines.AddStrings(TMimePart(FPartList[n]).Lines);
|
|
end;
|
|
FLines.Add('--' + bound + '--');
|
|
with TMimePart.Create do
|
|
try
|
|
Self.FLines.SaveToStream(DecodedLines);
|
|
Primary := 'Multipart';
|
|
Secondary := FMultipartType;
|
|
Description := 'Multipart message';
|
|
Boundary := bound;
|
|
EncodePart;
|
|
Self.FLines.Assign(Lines);
|
|
finally
|
|
Free;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
procedure TMimeMess.FinalizeHeaders;
|
|
begin
|
|
FHeader.EncodeHeaders(FLines);
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
procedure TMimeMess.ParseHeaders;
|
|
begin
|
|
FHeader.DecodeHeaders(FLines);
|
|
end;
|
|
|
|
{==============================================================================}
|
|
|
|
procedure TMimeMess.DecodeMessage;
|
|
var
|
|
l: TStringList;
|
|
m: TMimePart;
|
|
i: Integer;
|
|
bound: string;
|
|
begin
|
|
l := TStringList.Create;
|
|
m := TMimePart.Create;
|
|
try
|
|
l.Assign(FLines);
|
|
FHeader.Clear;
|
|
ParseHeaders;
|
|
m.ExtractPart(l, 0);
|
|
if m.PrimaryCode = MP_MULTIPART then
|
|
begin
|
|
bound := m.Boundary;
|
|
i := 0;
|
|
repeat
|
|
with TMimePart(PartList[AddPart]) do
|
|
begin
|
|
Boundary := bound;
|
|
i := ExtractPart(l, i);
|
|
DecodePart;
|
|
end;
|
|
until i >= l.Count - 2;
|
|
end
|
|
else
|
|
begin
|
|
with TMimePart(PartList[AddPart]) do
|
|
begin
|
|
ExtractPart(l, 0);
|
|
DecodePart;
|
|
end;
|
|
end;
|
|
finally
|
|
m.Free;
|
|
l.Free;
|
|
end;
|
|
end;
|
|
|
|
end.
|