123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851 |
- {==============================================================================|
- | Project : Ararat Synapse | 002.006.001 |
- |==============================================================================|
- | Content: MIME message object |
- |==============================================================================|
- | Copyright (c)1999-2021, Lukas Gebauer |
- | All rights reserved. |
- | |
- | Redistribution and use in source and binary forms, with or without |
- | modification, are permitted provided that the following conditions are met: |
- | |
- | Redistributions of source code must retain the above copyright notice, this |
- | list of conditions and the following disclaimer. |
- | |
- | Redistributions in binary form must reproduce the above copyright notice, |
- | this list of conditions and the following disclaimer in the documentation |
- | and/or other materials provided with the distribution. |
- | |
- | Neither the name of Lukas Gebauer nor the names of its contributors may |
- | be used to endorse or promote products derived from this software without |
- | specific prior written permission. |
- | |
- | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
- | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
- | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
- | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
- | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
- | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
- | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
- | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
- | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
- | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
- | DAMAGE. |
- |==============================================================================|
- | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
- | Portions created by Lukas Gebauer are Copyright (c)2000-2021. |
- | Portions created by Petr Fejfar are Copyright (c)2011-2012. |
- | All Rights Reserved. |
- |==============================================================================|
- | Contributor(s): |
- |==============================================================================|
- | History: see HISTORY.HTM From distribution package |
- | (Found at URL: http://www.ararat.cz/synapse/) |
- |==============================================================================}
- {:@abstract(MIME message handling)
- Classes for easy handling with e-mail message.
- }
- {$IFDEF FPC}
- {$MODE DELPHI}
- {$ENDIF}
- {$H+}
- {$M+}
- unit mimemess;
- interface
- uses
- Classes, SysUtils,
- mimepart, synachar, synautil, mimeinln;
- type
- {:Possible values for message priority}
- TMessPriority = (MP_unknown, MP_low, MP_normal, MP_high);
- {:@abstract(Object for basic e-mail header fields.)}
- TMessHeader = class(TObject)
- private
- FFrom: string;
- FToList: TStringList;
- FCCList: TStringList;
- FSubject: string;
- FOrganization: string;
- FCustomHeaders: TStringList;
- FDate: TDateTime;
- FXMailer: string;
- FCharsetCode: TMimeChar;
- FReplyTo: string;
- FMessageID: string;
- FPriority: TMessPriority;
- Fpri: TMessPriority;
- Fxpri: TMessPriority;
- Fxmspri: TMessPriority;
- protected
- function ParsePriority(value: string): TMessPriority;
- function DecodeHeader(value: string): boolean; virtual;
- public
- constructor Create; virtual;
- destructor Destroy; override;
- {:Clears all data fields.}
- procedure Clear; virtual;
- {Add headers from from this object to Value.}
- procedure EncodeHeaders(const Value: TStrings); virtual;
- {:Parse header from Value to this object.}
- procedure DecodeHeaders(const Value: TStrings);
- {:Try find specific header in CustomHeader. Search is case insensitive.
- This is good for reading any non-parsed header.}
- function FindHeader(Value: string): string;
- {:Try find specific headers in CustomHeader. This metod is for repeatly used
- headers like 'received' header, etc. Search is case insensitive.
- This is good for reading ano non-parsed header.}
- procedure FindHeaderList(Value: string; const HeaderList: TStrings);
- published
- {:Sender of message.}
- property From: string read FFrom Write FFrom;
- {:Stringlist with receivers of message. (one per line)}
- property ToList: TStringList read FToList;
- {:Stringlist with Carbon Copy receivers of message. (one per line)}
- property CCList: TStringList read FCCList;
- {:Subject of message.}
- property Subject: string read FSubject Write FSubject;
- {:Organization string.}
- property Organization: string read FOrganization Write FOrganization;
- {:After decoding contains all headers lines witch not have parsed to any
- other structures in this object. It mean: this conatins all other headers
- except:
- X-MAILER, FROM, SUBJECT, ORGANIZATION, TO, CC, DATE, MIME-VERSION,
- CONTENT-TYPE, CONTENT-DESCRIPTION, CONTENT-DISPOSITION, CONTENT-ID,
- CONTENT-TRANSFER-ENCODING, REPLY-TO, MESSAGE-ID, X-MSMAIL-PRIORITY,
- X-PRIORITY, PRIORITY
- When you encode headers, all this lines is added as headers. Be carefull
- for duplicites!}
- property CustomHeaders: TStringList read FCustomHeaders;
- {:Date and time of message.}
- property Date: TDateTime read FDate Write FDate;
- {:Mailer identification.}
- property XMailer: string read FXMailer Write FXMailer;
- {:Address for replies}
- property ReplyTo: string read FReplyTo Write FReplyTo;
- {:message indetifier}
- property MessageID: string read FMessageID Write FMessageID;
- {:message priority}
- property Priority: TMessPriority read FPriority Write FPriority;
- {:Specify base charset. By default is used system charset.}
- property CharsetCode: TMimeChar read FCharsetCode Write FCharsetCode;
- end;
- TMessHeaderClass = class of TMessHeader;
- {:@abstract(Object for handling of e-mail message.)}
- TMimeMess = class(TObject)
- private
- FMessagePart: TMimePart;
- FLines: TStringList;
- FHeader: TMessHeader;
- public
- constructor Create;
- {:create this object and assign your own descendant of @link(TMessHeader)
- object to @link(header) property. So, you can create your own message
- headers parser and use it by this object.}
- constructor CreateAltHeaders(HeadClass: TMessHeaderClass);
- destructor Destroy; override;
- {:Reset component to default state.}
- procedure Clear; virtual;
- {:Add MIME part as subpart of PartParent. If you need set root MIME part,
- then set as PartParent @NIL value. If you need set more then one subpart,
- you must have PartParent of multipart type!}
- function AddPart(const PartParent: TMimePart): TMimePart;
- {:Add MIME part as subpart of PartParent. If you need set root MIME part,
- then set as PartParent @NIL value. If you need set more then 1 subpart, you
- must have PartParent of multipart type!
- This part is marked as multipart with secondary MIME type specified by
- MultipartType parameter. (typical value is 'mixed')
- This part can be used as PartParent for another parts (include next
- multipart). If you need only one part, then you not need Multipart part.}
- function AddPartMultipart(const MultipartType: String; const PartParent: TMimePart): TMimePart;
- {:Add MIME part as subpart of PartParent. If you need set root MIME part,
- then set as PartParent @NIL value. If you need set more then 1 subpart, you
- must have PartParent of multipart type!
- After creation of part set type to text part and set all necessary
- properties. Content of part is readed from value stringlist.}
- function AddPartText(const Value: TStrings; const PartParent: TMimePart): TMimepart;
- {:Add MIME part as subpart of PartParent. If you need set root MIME part,
- then set as PartParent @NIL value. If you need set more then 1 subpart, you
- must have PartParent of multipart type!
- After creation of part set type to text part and set all necessary
- properties. Content of part is readed from value stringlist. You can select
- your charset and your encoding type. If Raw is @true, then it not doing
- charset conversion!}
- function AddPartTextEx(const Value: TStrings; const PartParent: TMimePart;
- PartCharset: TMimeChar; Raw: Boolean; PartEncoding: TMimeEncoding): TMimepart;
- {:Add MIME part as subpart of PartParent. If you need set root MIME part,
- then set as PartParent @NIL value. If you need set more then 1 subpart, you
- must have PartParent of multipart type!
- After creation of part set type to text part to HTML type and set all
- necessary properties. Content of HTML part is readed from Value stringlist.}
- function AddPartHTML(const Value: TStrings; const PartParent: TMimePart): TMimepart;
- {:Same as @link(AddPartText), but content is readed from file}
- function AddPartTextFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
- {:Same as @link(AddPartHTML), but content is readed from file}
- function AddPartHTMLFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
- {:Add MIME part as subpart of PartParent. If you need set root MIME part,
- then set as PartParent @NIL value. If you need set more then 1 subpart,
- you must have PartParent of multipart type!
- After creation of part set type to binary and set all necessary properties.
- MIME primary and secondary types defined automaticly by filename extension.
- Content of binary part is readed from Stream. This binary part is encoded
- as file attachment.}
- function AddPartBinary(const Stream: TStream; const FileName: string; const PartParent: TMimePart): TMimepart;
- {:Same as @link(AddPartBinary), but content is readed from file}
- function AddPartBinaryFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;
- {:Add MIME part as subpart of PartParent. If you need set root MIME part,
- then set as PartParent @NIL value. If you need set more then 1 subpart, you
- must have PartParent of multipart type!
- After creation of part set type to binary and set all necessary properties.
- MIME primary and secondary types defined automaticly by filename extension.
- Content of binary part is readed from Stream.
- This binary part is encoded as inline data with given Conten ID (cid).
- Content ID can be used as reference ID in HTML source in HTML part.}
- function AddPartHTMLBinary(const Stream: TStream; const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
- {:Same as @link(AddPartHTMLBinary), but content is readed from file}
- function AddPartHTMLBinaryFromFile(const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
- {:Add MIME part as subpart of PartParent. If you need set root MIME part,
- then set as PartParent @NIL value. If you need set more then 1 subpart, you
- must have PartParent of multipart type!
- After creation of part set type to message and set all necessary properties.
- MIME primary and secondary types are setted to 'message/rfc822'.
- Content of raw RFC-822 message is readed from Stream.}
- function AddPartMess(const Value: TStrings; const PartParent: TMimePart): TMimepart;
- {:Same as @link(AddPartMess), but content is readed from file}
- function AddPartMessFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;
- {:Compose message from @link(MessagePart) to @link(Lines). Headers from
- @link(Header) object is added also.}
- procedure EncodeMessage; virtual;
- {:Decode message from @link(Lines) to @link(MessagePart). Massage headers
- are parsed into @link(Header) object.}
- procedure DecodeMessage; virtual;
- {pf}
- {: HTTP message is received by @link(THTTPSend) component in two parts:
- headers are stored in @link(THTTPSend.Headers) and a body in memory stream
- @link(THTTPSend.Document).
- On the top of it, HTTP connections are always 8-bit, hence data are
- transferred in native format i.e. no transfer encoding is applied.
- This method operates the similiar way and produces the same
- result as @link(DecodeMessage).
- }
- procedure DecodeMessageBinary(AHeader:TStrings; AData:TMemoryStream);
- {/pf}
- published
- {:@link(TMimePart) object with decoded MIME message. This object can handle
- any number of nested @link(TMimePart) objects itself. It is used for handle
- any tree of MIME subparts.}
- property MessagePart: TMimePart read FMessagePart;
- {:Raw MIME encoded message.}
- property Lines: TStringList read FLines;
- {:Object for e-mail header fields. This object is created automaticly.
- Do not free this object!}
- property Header: TMessHeader read FHeader;
- end;
- implementation
- {==============================================================================}
- constructor TMessHeader.Create;
- begin
- inherited Create;
- FToList := CreateStringList;
- FCCList := CreateStringList;
- FCustomHeaders := CreateStringList;
- FCharsetCode := GetCurCP;
- 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 := '';
- FReplyTo := '';
- FMessageID := '';
- FPriority := MP_unknown;
- end;
- procedure TMessHeader.EncodeHeaders(const Value: TStrings);
- 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 FPriority <> MP_unknown then
- case FPriority of
- MP_high:
- begin
- Value.Insert(0, 'X-MSMAIL-Priority: High');
- Value.Insert(0, 'X-Priority: 1');
- Value.Insert(0, 'Priority: urgent');
- end;
- MP_low:
- begin
- Value.Insert(0, 'X-MSMAIL-Priority: low');
- Value.Insert(0, 'X-Priority: 5');
- Value.Insert(0, 'Priority: non-urgent');
- end;
- end;
- if FReplyTo <> '' then
- Value.Insert(0, 'Reply-To: ' + GetEmailAddr(FReplyTo));
- if FMessageID <> '' then
- Value.Insert(0, 'Message-ID: <' + trim(FMessageID) + '>');
- if FXMailer = '' then
- Value.Insert(0, 'X-mailer: Synapse - Pascal 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: ' + InlineCodeEx(FOrganization, FCharsetCode));
- s := '';
- for n := 0 to FCCList.Count - 1 do
- if s = '' then
- s := InlineEmailEx(FCCList[n], FCharsetCode)
- else
- s := s + ', ' + InlineEmailEx(FCCList[n], FCharsetCode);
- if s <> '' then
- Value.Insert(0, 'CC: ' + s);
- Value.Insert(0, 'Date: ' + Rfc822DateTime(FDate));
- if FSubject <> '' then
- Value.Insert(0, 'Subject: ' + InlineCodeEx(FSubject, FCharsetCode));
- s := '';
- for n := 0 to FToList.Count - 1 do
- if s = '' then
- s := InlineEmailEx(FToList[n], FCharsetCode)
- else
- s := s + ', ' + InlineEmailEx(FToList[n], FCharsetCode);
- if s <> '' then
- Value.Insert(0, 'To: ' + s);
- Value.Insert(0, 'From: ' + InlineEmailEx(FFrom, FCharsetCode));
- end;
- function TMessHeader.ParsePriority(value: string): TMessPriority;
- var
- s: string;
- x: integer;
- begin
- Result := MP_unknown;
- s := Trim(separateright(value, ':'));
- s := Separateleft(s, ' ');
- x := StrToIntDef(s, -1);
- if x >= 0 then
- case x of
- 1, 2:
- Result := MP_High;
- 3:
- Result := MP_Normal;
- 4, 5:
- Result := MP_Low;
- end
- else
- begin
- s := lowercase(s);
- if (s = 'urgent') or (s = 'high') or (s = 'highest') then
- Result := MP_High;
- if (s = 'normal') or (s = 'medium') then
- Result := MP_Normal;
- if (s = 'low') or (s = 'lowest')
- or (s = 'no-priority') or (s = 'non-urgent') then
- Result := MP_Low;
- end;
- end;
- function TMessHeader.DecodeHeader(value: string): boolean;
- var
- s, t: string;
- cp: TMimeChar;
- begin
- Result := True;
- cp := FCharsetCode;
- s := uppercase(value);
- if Pos('X-MAILER:', s) = 1 then
- begin
- FXMailer := Trim(SeparateRight(Value, ':'));
- Exit;
- end;
- if Pos('FROM:', s) = 1 then
- begin
- FFrom := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
- Exit;
- end;
- if Pos('SUBJECT:', s) = 1 then
- begin
- FSubject := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
- Exit;
- end;
- if Pos('ORGANIZATION:', s) = 1 then
- begin
- FOrganization := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
- Exit;
- end;
- if Pos('TO:', s) = 1 then
- begin
- s := Trim(SeparateRight(Value, ':'));
- repeat
- t := InlineDecode(Trim(FetchEx(s, ',', '"')), cp);
- if t <> '' then
- FToList.Add(t);
- until s = '';
- Exit;
- end;
- if Pos('CC:', s) = 1 then
- begin
- s := Trim(SeparateRight(Value, ':'));
- repeat
- t := InlineDecode(Trim(FetchEx(s, ',', '"')), cp);
- if t <> '' then
- FCCList.Add(t);
- until s = '';
- Exit;
- end;
- if Pos('DATE:', s) = 1 then
- begin
- FDate := DecodeRfcDateTime(Trim(SeparateRight(Value, ':')));
- Exit;
- end;
- if Pos('REPLY-TO:', s) = 1 then
- begin
- FReplyTo := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
- Exit;
- end;
- if Pos('MESSAGE-ID:', s) = 1 then
- begin
- FMessageID := GetEmailAddr(Trim(SeparateRight(Value, ':')));
- Exit;
- end;
- if Pos('PRIORITY:', s) = 1 then
- begin
- FPri := ParsePriority(value);
- Exit;
- end;
- if Pos('X-PRIORITY:', s) = 1 then
- begin
- FXPri := ParsePriority(value);
- Exit;
- end;
- if Pos('X-MSMAIL-PRIORITY:', s) = 1 then
- begin
- FXmsPri := ParsePriority(value);
- Exit;
- end;
- if Pos('MIME-VERSION:', s) = 1 then
- Exit;
- if Pos('CONTENT-TYPE:', s) = 1 then
- Exit;
- if Pos('CONTENT-DESCRIPTION:', s) = 1 then
- Exit;
- if Pos('CONTENT-DISPOSITION:', s) = 1 then
- Exit;
- if Pos('CONTENT-ID:', s) = 1 then
- Exit;
- if Pos('CONTENT-TRANSFER-ENCODING:', s) = 1 then
- Exit;
- Result := False;
- end;
- procedure TMessHeader.DecodeHeaders(const Value: TStrings);
- var
- s: string;
- x: Integer;
- begin
- Clear;
- Fpri := MP_unknown;
- Fxpri := MP_unknown;
- Fxmspri := MP_unknown;
- x := 0;
- while Value.Count > x do
- begin
- s := NormalizeHeader(Value, x);
- if s = '' then
- Break;
- if not DecodeHeader(s) then
- FCustomHeaders.Add(s);
- end;
- if Fpri <> MP_unknown then
- FPriority := Fpri
- else
- if Fxpri <> MP_unknown then
- FPriority := Fxpri
- else
- if Fxmspri <> MP_unknown then
- FPriority := Fxmspri
- end;
- function TMessHeader.FindHeader(Value: string): string;
- var
- n: integer;
- begin
- Result := '';
- for n := 0 to FCustomHeaders.Count - 1 do
- if Pos(UpperCase(Value), UpperCase(FCustomHeaders[n])) = 1 then
- begin
- Result := Trim(SeparateRight(FCustomHeaders[n], ':'));
- break;
- end;
- end;
- procedure TMessHeader.FindHeaderList(Value: string; const HeaderList: TStrings);
- var
- n: integer;
- begin
- HeaderList.Clear;
- for n := 0 to FCustomHeaders.Count - 1 do
- if Pos(UpperCase(Value), UpperCase(FCustomHeaders[n])) = 1 then
- begin
- HeaderList.Add(Trim(SeparateRight(FCustomHeaders[n], ':')));
- end;
- end;
- {==============================================================================}
- constructor TMimeMess.Create;
- begin
- CreateAltHeaders(TMessHeader);
- end;
- constructor TMimeMess.CreateAltHeaders(HeadClass: TMessHeaderClass);
- begin
- inherited Create;
- FMessagePart := TMimePart.Create;
- FLines := CreateStringList;
- FHeader := HeadClass.Create;
- end;
- destructor TMimeMess.Destroy;
- begin
- FMessagePart.Free;
- FHeader.Free;
- FLines.Free;
- inherited Destroy;
- end;
- {==============================================================================}
- procedure TMimeMess.Clear;
- begin
- FMessagePart.Clear;
- FLines.Clear;
- FHeader.Clear;
- end;
- {==============================================================================}
- function TMimeMess.AddPart(const PartParent: TMimePart): TMimePart;
- begin
- if PartParent = nil then
- Result := FMessagePart
- else
- Result := PartParent.AddSubPart;
- Result.Clear;
- end;
- {==============================================================================}
- function TMimeMess.AddPartMultipart(const MultipartType: String; const PartParent: TMimePart): TMimePart;
- begin
- Result := AddPart(PartParent);
- with Result do
- begin
- Primary := 'Multipart';
- Secondary := MultipartType;
- Description := 'Multipart message';
- Boundary := GenerateBoundary;
- EncodePartHeader;
- end;
- end;
- function TMimeMess.AddPartText(const Value: TStrings; const PartParent: TMimePart): TMimepart;
- begin
- Result := AddPart(PartParent);
- with Result do
- begin
- Value.SaveToStream(DecodedLines);
- Primary := 'text';
- Secondary := 'plain';
- Description := 'Message text';
- Disposition := 'inline';
- CharsetCode := IdealCharsetCoding(Value.Text, TargetCharset, IdealCharsets);
- EncodingCode := ME_QUOTED_PRINTABLE;
- EncodePart;
- EncodePartHeader;
- end;
- end;
- function TMimeMess.AddPartTextEx(const Value: TStrings; const PartParent: TMimePart;
- PartCharset: TMimeChar; Raw: Boolean; PartEncoding: TMimeEncoding): TMimepart;
- begin
- Result := AddPart(PartParent);
- with Result do
- begin
- Value.SaveToStream(DecodedLines);
- Primary := 'text';
- Secondary := 'plain';
- Description := 'Message text';
- Disposition := 'inline';
- CharsetCode := PartCharset;
- EncodingCode := PartEncoding;
- ConvertCharset := not Raw;
- EncodePart;
- EncodePartHeader;
- end;
- end;
- function TMimeMess.AddPartHTML(const Value: TStrings; const PartParent: TMimePart): TMimepart;
- begin
- Result := AddPart(PartParent);
- with Result do
- begin
- Value.SaveToStream(DecodedLines);
- Primary := 'text';
- Secondary := 'html';
- Description := 'HTML text';
- Disposition := 'inline';
- CharsetCode := UTF_8;
- EncodingCode := ME_QUOTED_PRINTABLE;
- EncodePart;
- EncodePartHeader;
- end;
- end;
- function TMimeMess.AddPartTextFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
- var
- tmp: TStrings;
- begin
- tmp := CreateStringList;
- try
- tmp.LoadFromFile(FileName);
- Result := AddPartText(tmp, PartParent);
- Finally
- tmp.Free;
- end;
- end;
- function TMimeMess.AddPartHTMLFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
- var
- tmp: TStrings;
- begin
- tmp := CreateStringList;
- try
- tmp.LoadFromFile(FileName);
- Result := AddPartHTML(tmp, PartParent);
- Finally
- tmp.Free;
- end;
- end;
- function TMimeMess.AddPartBinary(const Stream: TStream; const FileName: string; const PartParent: TMimePart): TMimepart;
- begin
- Result := AddPart(PartParent);
- Result.DecodedLines.LoadFromStream(Stream);
- Result.MimeTypeFromExt(FileName);
- Result.Description := 'Attached file: ' + FileName;
- Result.Disposition := 'attachment';
- Result.FileName := FileName;
- Result.EncodingCode := ME_BASE64;
- Result.EncodePart;
- Result.EncodePartHeader;
- end;
- function TMimeMess.AddPartBinaryFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;
- var
- tmp: TMemoryStream;
- begin
- tmp := TMemoryStream.Create;
- try
- tmp.LoadFromFile(FileName);
- Result := AddPartBinary(tmp, ExtractFileName(FileName), PartParent);
- finally
- tmp.Free;
- end;
- end;
- function TMimeMess.AddPartHTMLBinary(const Stream: TStream; const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
- begin
- Result := AddPart(PartParent);
- Result.DecodedLines.LoadFromStream(Stream);
- Result.MimeTypeFromExt(FileName);
- Result.Description := 'Included file: ' + FileName;
- Result.Disposition := 'inline';
- Result.ContentID := Cid;
- Result.FileName := FileName;
- Result.EncodingCode := ME_BASE64;
- Result.EncodePart;
- Result.EncodePartHeader;
- end;
- function TMimeMess.AddPartHTMLBinaryFromFile(const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
- var
- tmp: TMemoryStream;
- begin
- tmp := TMemoryStream.Create;
- try
- tmp.LoadFromFile(FileName);
- Result :=AddPartHTMLBinary(tmp, ExtractFileName(FileName), Cid, PartParent);
- finally
- tmp.Free;
- end;
- end;
- function TMimeMess.AddPartMess(const Value: TStrings; const PartParent: TMimePart): TMimepart;
- var
- part: Tmimepart;
- begin
- Result := AddPart(PartParent);
- part := AddPart(result);
- part.lines.addstrings(Value);
- part.DecomposeParts;
- with Result do
- begin
- Primary := 'message';
- Secondary := 'rfc822';
- Description := 'E-mail Message';
- EncodePart;
- EncodePartHeader;
- end;
- end;
- function TMimeMess.AddPartMessFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
- var
- tmp: TStrings;
- begin
- tmp := CreateStringList;
- try
- tmp.LoadFromFile(FileName);
- Result := AddPartMess(tmp, PartParent);
- Finally
- tmp.Free;
- end;
- end;
- {==============================================================================}
- procedure TMimeMess.EncodeMessage;
- var
- l: TStringList;
- x: integer;
- begin
- //merge headers from THeaders and header field from MessagePart
- l := CreateStringList;
- try
- FHeader.EncodeHeaders(l);
- x := IndexByBegin('CONTENT-TYPE', FMessagePart.Headers);
- if x >= 0 then
- l.add(FMessagePart.Headers[x]);
- x := IndexByBegin('CONTENT-DESCRIPTION', FMessagePart.Headers);
- if x >= 0 then
- l.add(FMessagePart.Headers[x]);
- x := IndexByBegin('CONTENT-DISPOSITION', FMessagePart.Headers);
- if x >= 0 then
- l.add(FMessagePart.Headers[x]);
- x := IndexByBegin('CONTENT-ID', FMessagePart.Headers);
- if x >= 0 then
- l.add(FMessagePart.Headers[x]);
- x := IndexByBegin('CONTENT-TRANSFER-ENCODING', FMessagePart.Headers);
- if x >= 0 then
- l.add(FMessagePart.Headers[x]);
- FMessagePart.Headers.Assign(l);
- finally
- l.Free;
- end;
- FMessagePart.ComposeParts;
- FLines.Assign(FMessagePart.Lines);
- end;
- {==============================================================================}
- procedure TMimeMess.DecodeMessage;
- begin
- FHeader.Clear;
- FHeader.DecodeHeaders(FLines);
- FMessagePart.Lines.Assign(FLines);
- FMessagePart.DecomposeParts;
- end;
- {pf}
- procedure TMimeMess.DecodeMessageBinary(AHeader:TStrings; AData:TMemoryStream);
- begin
- FHeader.Clear;
- FLines.Clear;
- FLines.Assign(AHeader);
- FHeader.DecodeHeaders(FLines);
- FMessagePart.DecomposePartsBinary(AHeader,PChar(AData.Memory),PChar(AData.Memory)+AData.Size);
- end;
- {/pf}
- end.
|