source: trunk/Packages/synapse/source/lib/mimemess.pas

Last change on this file was 2, checked in by chronos, 12 years ago
  • Přidáno: Základní kostra projektu.
  • Přidáno: Knihovna synapse.
File size: 28.0 KB
Line 
1{==============================================================================|
2| Project : Ararat Synapse | 002.006.000 |
3|==============================================================================|
4| Content: MIME message object |
5|==============================================================================|
6| Copyright (c)1999-2012, Lukas Gebauer |
7| All rights reserved. |
8| |
9| Redistribution and use in source and binary forms, with or without |
10| modification, are permitted provided that the following conditions are met: |
11| |
12| Redistributions of source code must retain the above copyright notice, this |
13| list of conditions and the following disclaimer. |
14| |
15| Redistributions in binary form must reproduce the above copyright notice, |
16| this list of conditions and the following disclaimer in the documentation |
17| and/or other materials provided with the distribution. |
18| |
19| Neither the name of Lukas Gebauer nor the names of its contributors may |
20| be used to endorse or promote products derived from this software without |
21| specific prior written permission. |
22| |
23| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
24| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
25| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26| ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
27| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
28| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
29| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
30| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
31| LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
32| OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
33| DAMAGE. |
34|==============================================================================|
35| The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
36| Portions created by Lukas Gebauer are Copyright (c)2000-2012. |
37| Portions created by Petr Fejfar are Copyright (c)2011-2012. |
38| All Rights Reserved. |
39|==============================================================================|
40| Contributor(s): |
41|==============================================================================|
42| History: see HISTORY.HTM From distribution package |
43| (Found at URL: http://www.ararat.cz/synapse/) |
44|==============================================================================}
45
46{:@abstract(MIME message handling)
47Classes for easy handling with e-mail message.
48}
49
50{$IFDEF FPC}
51 {$MODE DELPHI}
52{$ENDIF}
53{$H+}
54{$M+}
55
56unit mimemess;
57
58interface
59
60uses
61 Classes, SysUtils,
62 mimepart, synachar, synautil, mimeinln;
63
64type
65
66 {:Possible values for message priority}
67 TMessPriority = (MP_unknown, MP_low, MP_normal, MP_high);
68
69 {:@abstract(Object for basic e-mail header fields.)}
70 TMessHeader = class(TObject)
71 private
72 FFrom: string;
73 FToList: TStringList;
74 FCCList: TStringList;
75 FSubject: string;
76 FOrganization: string;
77 FCustomHeaders: TStringList;
78 FDate: TDateTime;
79 FXMailer: string;
80 FCharsetCode: TMimeChar;
81 FReplyTo: string;
82 FMessageID: string;
83 FPriority: TMessPriority;
84 Fpri: TMessPriority;
85 Fxpri: TMessPriority;
86 Fxmspri: TMessPriority;
87 protected
88 function ParsePriority(value: string): TMessPriority;
89 function DecodeHeader(value: string): boolean; virtual;
90 public
91 constructor Create; virtual;
92 destructor Destroy; override;
93
94 {:Clears all data fields.}
95 procedure Clear; virtual;
96
97 {Add headers from from this object to Value.}
98 procedure EncodeHeaders(const Value: TStrings); virtual;
99
100 {:Parse header from Value to this object.}
101 procedure DecodeHeaders(const Value: TStrings);
102
103 {:Try find specific header in CustomHeader. Search is case insensitive.
104 This is good for reading any non-parsed header.}
105 function FindHeader(Value: string): string;
106
107 {:Try find specific headers in CustomHeader. This metod is for repeatly used
108 headers like 'received' header, etc. Search is case insensitive.
109 This is good for reading ano non-parsed header.}
110 procedure FindHeaderList(Value: string; const HeaderList: TStrings);
111 published
112 {:Sender of message.}
113 property From: string read FFrom Write FFrom;
114
115 {:Stringlist with receivers of message. (one per line)}
116 property ToList: TStringList read FToList;
117
118 {:Stringlist with Carbon Copy receivers of message. (one per line)}
119 property CCList: TStringList read FCCList;
120
121 {:Subject of message.}
122 property Subject: string read FSubject Write FSubject;
123
124 {:Organization string.}
125 property Organization: string read FOrganization Write FOrganization;
126
127 {:After decoding contains all headers lines witch not have parsed to any
128 other structures in this object. It mean: this conatins all other headers
129 except:
130
131 X-MAILER, FROM, SUBJECT, ORGANIZATION, TO, CC, DATE, MIME-VERSION,
132 CONTENT-TYPE, CONTENT-DESCRIPTION, CONTENT-DISPOSITION, CONTENT-ID,
133 CONTENT-TRANSFER-ENCODING, REPLY-TO, MESSAGE-ID, X-MSMAIL-PRIORITY,
134 X-PRIORITY, PRIORITY
135
136 When you encode headers, all this lines is added as headers. Be carefull
137 for duplicites!}
138 property CustomHeaders: TStringList read FCustomHeaders;
139
140 {:Date and time of message.}
141 property Date: TDateTime read FDate Write FDate;
142
143 {:Mailer identification.}
144 property XMailer: string read FXMailer Write FXMailer;
145
146 {:Address for replies}
147 property ReplyTo: string read FReplyTo Write FReplyTo;
148
149 {:message indetifier}
150 property MessageID: string read FMessageID Write FMessageID;
151
152 {:message priority}
153 property Priority: TMessPriority read FPriority Write FPriority;
154
155 {:Specify base charset. By default is used system charset.}
156 property CharsetCode: TMimeChar read FCharsetCode Write FCharsetCode;
157 end;
158
159 TMessHeaderClass = class of TMessHeader;
160
161 {:@abstract(Object for handling of e-mail message.)}
162 TMimeMess = class(TObject)
163 private
164 FMessagePart: TMimePart;
165 FLines: TStringList;
166 FHeader: TMessHeader;
167 public
168 constructor Create;
169 {:create this object and assign your own descendant of @link(TMessHeader)
170 object to @link(header) property. So, you can create your own message
171 headers parser and use it by this object.}
172 constructor CreateAltHeaders(HeadClass: TMessHeaderClass);
173 destructor Destroy; override;
174
175 {:Reset component to default state.}
176 procedure Clear; virtual;
177
178 {:Add MIME part as subpart of PartParent. If you need set root MIME part,
179 then set as PartParent @NIL value. If you need set more then one subpart,
180 you must have PartParent of multipart type!}
181 function AddPart(const PartParent: TMimePart): TMimePart;
182
183 {:Add MIME part as subpart of PartParent. If you need set root MIME part,
184 then set as PartParent @NIL value. If you need set more then 1 subpart, you
185 must have PartParent of multipart type!
186
187 This part is marked as multipart with secondary MIME type specified by
188 MultipartType parameter. (typical value is 'mixed')
189
190 This part can be used as PartParent for another parts (include next
191 multipart). If you need only one part, then you not need Multipart part.}
192 function AddPartMultipart(const MultipartType: String; const PartParent: TMimePart): TMimePart;
193
194 {:Add MIME part as subpart of PartParent. If you need set root MIME part,
195 then set as PartParent @NIL value. If you need set more then 1 subpart, you
196 must have PartParent of multipart type!
197
198 After creation of part set type to text part and set all necessary
199 properties. Content of part is readed from value stringlist.}
200 function AddPartText(const Value: TStrings; const PartParent: TMimePart): TMimepart;
201
202 {:Add MIME part as subpart of PartParent. If you need set root MIME part,
203 then set as PartParent @NIL value. If you need set more then 1 subpart, you
204 must have PartParent of multipart type!
205
206 After creation of part set type to text part and set all necessary
207 properties. Content of part is readed from value stringlist. You can select
208 your charset and your encoding type. If Raw is @true, then it not doing
209 charset conversion!}
210 function AddPartTextEx(const Value: TStrings; const PartParent: TMimePart;
211 PartCharset: TMimeChar; Raw: Boolean; PartEncoding: TMimeEncoding): TMimepart;
212
213 {:Add MIME part as subpart of PartParent. If you need set root MIME part,
214 then set as PartParent @NIL value. If you need set more then 1 subpart, you
215 must have PartParent of multipart type!
216
217 After creation of part set type to text part to HTML type and set all
218 necessary properties. Content of HTML part is readed from Value stringlist.}
219 function AddPartHTML(const Value: TStrings; const PartParent: TMimePart): TMimepart;
220
221 {:Same as @link(AddPartText), but content is readed from file}
222 function AddPartTextFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
223
224 {:Same as @link(AddPartHTML), but content is readed from file}
225 function AddPartHTMLFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
226
227 {:Add MIME part as subpart of PartParent. If you need set root MIME part,
228 then set as PartParent @NIL value. If you need set more then 1 subpart,
229 you must have PartParent of multipart type!
230
231 After creation of part set type to binary and set all necessary properties.
232 MIME primary and secondary types defined automaticly by filename extension.
233 Content of binary part is readed from Stream. This binary part is encoded
234 as file attachment.}
235 function AddPartBinary(const Stream: TStream; const FileName: string; const PartParent: TMimePart): TMimepart;
236
237 {:Same as @link(AddPartBinary), but content is readed from file}
238 function AddPartBinaryFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;
239
240 {:Add MIME part as subpart of PartParent. If you need set root MIME part,
241 then set as PartParent @NIL value. If you need set more then 1 subpart, you
242 must have PartParent of multipart type!
243
244 After creation of part set type to binary and set all necessary properties.
245 MIME primary and secondary types defined automaticly by filename extension.
246 Content of binary part is readed from Stream.
247
248 This binary part is encoded as inline data with given Conten ID (cid).
249 Content ID can be used as reference ID in HTML source in HTML part.}
250 function AddPartHTMLBinary(const Stream: TStream; const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
251
252 {:Same as @link(AddPartHTMLBinary), but content is readed from file}
253 function AddPartHTMLBinaryFromFile(const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
254
255 {:Add MIME part as subpart of PartParent. If you need set root MIME part,
256 then set as PartParent @NIL value. If you need set more then 1 subpart, you
257 must have PartParent of multipart type!
258
259 After creation of part set type to message and set all necessary properties.
260 MIME primary and secondary types are setted to 'message/rfc822'.
261 Content of raw RFC-822 message is readed from Stream.}
262 function AddPartMess(const Value: TStrings; const PartParent: TMimePart): TMimepart;
263
264 {:Same as @link(AddPartMess), but content is readed from file}
265 function AddPartMessFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;
266
267 {:Compose message from @link(MessagePart) to @link(Lines). Headers from
268 @link(Header) object is added also.}
269 procedure EncodeMessage;
270
271 {:Decode message from @link(Lines) to @link(MessagePart). Massage headers
272 are parsed into @link(Header) object.}
273 procedure DecodeMessage;
274
275 {pf}
276 {: HTTP message is received by @link(THTTPSend) component in two parts:
277 headers are stored in @link(THTTPSend.Headers) and a body in memory stream
278 @link(THTTPSend.Document).
279
280 On the top of it, HTTP connections are always 8-bit, hence data are
281 transferred in native format i.e. no transfer encoding is applied.
282
283 This method operates the similiar way and produces the same
284 result as @link(DecodeMessage).
285 }
286 procedure DecodeMessageBinary(AHeader:TStrings; AData:TMemoryStream);
287 {/pf}
288 published
289 {:@link(TMimePart) object with decoded MIME message. This object can handle
290 any number of nested @link(TMimePart) objects itself. It is used for handle
291 any tree of MIME subparts.}
292 property MessagePart: TMimePart read FMessagePart;
293
294 {:Raw MIME encoded message.}
295 property Lines: TStringList read FLines;
296
297 {:Object for e-mail header fields. This object is created automaticly.
298 Do not free this object!}
299 property Header: TMessHeader read FHeader;
300 end;
301
302implementation
303
304{==============================================================================}
305
306constructor TMessHeader.Create;
307begin
308 inherited Create;
309 FToList := TStringList.Create;
310 FCCList := TStringList.Create;
311 FCustomHeaders := TStringList.Create;
312 FCharsetCode := GetCurCP;
313end;
314
315destructor TMessHeader.Destroy;
316begin
317 FCustomHeaders.Free;
318 FCCList.Free;
319 FToList.Free;
320 inherited Destroy;
321end;
322
323{==============================================================================}
324
325procedure TMessHeader.Clear;
326begin
327 FFrom := '';
328 FToList.Clear;
329 FCCList.Clear;
330 FSubject := '';
331 FOrganization := '';
332 FCustomHeaders.Clear;
333 FDate := 0;
334 FXMailer := '';
335 FReplyTo := '';
336 FMessageID := '';
337 FPriority := MP_unknown;
338end;
339
340procedure TMessHeader.EncodeHeaders(const Value: TStrings);
341var
342 n: Integer;
343 s: string;
344begin
345 if FDate = 0 then
346 FDate := Now;
347 for n := FCustomHeaders.Count - 1 downto 0 do
348 if FCustomHeaders[n] <> '' then
349 Value.Insert(0, FCustomHeaders[n]);
350 if FPriority <> MP_unknown then
351 case FPriority of
352 MP_high:
353 begin
354 Value.Insert(0, 'X-MSMAIL-Priority: High');
355 Value.Insert(0, 'X-Priority: 1');
356 Value.Insert(0, 'Priority: urgent');
357 end;
358 MP_low:
359 begin
360 Value.Insert(0, 'X-MSMAIL-Priority: low');
361 Value.Insert(0, 'X-Priority: 5');
362 Value.Insert(0, 'Priority: non-urgent');
363 end;
364 end;
365 if FReplyTo <> '' then
366 Value.Insert(0, 'Reply-To: ' + GetEmailAddr(FReplyTo));
367 if FMessageID <> '' then
368 Value.Insert(0, 'Message-ID: <' + trim(FMessageID) + '>');
369 if FXMailer = '' then
370 Value.Insert(0, 'X-mailer: Synapse - Pascal TCP/IP library by Lukas Gebauer')
371 else
372 Value.Insert(0, 'X-mailer: ' + FXMailer);
373 Value.Insert(0, 'MIME-Version: 1.0 (produced by Synapse)');
374 if FOrganization <> '' then
375 Value.Insert(0, 'Organization: ' + InlineCodeEx(FOrganization, FCharsetCode));
376 s := '';
377 for n := 0 to FCCList.Count - 1 do
378 if s = '' then
379 s := InlineEmailEx(FCCList[n], FCharsetCode)
380 else
381 s := s + ', ' + InlineEmailEx(FCCList[n], FCharsetCode);
382 if s <> '' then
383 Value.Insert(0, 'CC: ' + s);
384 Value.Insert(0, 'Date: ' + Rfc822DateTime(FDate));
385 if FSubject <> '' then
386 Value.Insert(0, 'Subject: ' + InlineCodeEx(FSubject, FCharsetCode));
387 s := '';
388 for n := 0 to FToList.Count - 1 do
389 if s = '' then
390 s := InlineEmailEx(FToList[n], FCharsetCode)
391 else
392 s := s + ', ' + InlineEmailEx(FToList[n], FCharsetCode);
393 if s <> '' then
394 Value.Insert(0, 'To: ' + s);
395 Value.Insert(0, 'From: ' + InlineEmailEx(FFrom, FCharsetCode));
396end;
397
398function TMessHeader.ParsePriority(value: string): TMessPriority;
399var
400 s: string;
401 x: integer;
402begin
403 Result := MP_unknown;
404 s := Trim(separateright(value, ':'));
405 s := Separateleft(s, ' ');
406 x := StrToIntDef(s, -1);
407 if x >= 0 then
408 case x of
409 1, 2:
410 Result := MP_High;
411 3:
412 Result := MP_Normal;
413 4, 5:
414 Result := MP_Low;
415 end
416 else
417 begin
418 s := lowercase(s);
419 if (s = 'urgent') or (s = 'high') or (s = 'highest') then
420 Result := MP_High;
421 if (s = 'normal') or (s = 'medium') then
422 Result := MP_Normal;
423 if (s = 'low') or (s = 'lowest')
424 or (s = 'no-priority') or (s = 'non-urgent') then
425 Result := MP_Low;
426 end;
427end;
428
429function TMessHeader.DecodeHeader(value: string): boolean;
430var
431 s, t: string;
432 cp: TMimeChar;
433begin
434 Result := True;
435 cp := FCharsetCode;
436 s := uppercase(value);
437 if Pos('X-MAILER:', s) = 1 then
438 begin
439 FXMailer := Trim(SeparateRight(Value, ':'));
440 Exit;
441 end;
442 if Pos('FROM:', s) = 1 then
443 begin
444 FFrom := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
445 Exit;
446 end;
447 if Pos('SUBJECT:', s) = 1 then
448 begin
449 FSubject := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
450 Exit;
451 end;
452 if Pos('ORGANIZATION:', s) = 1 then
453 begin
454 FOrganization := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
455 Exit;
456 end;
457 if Pos('TO:', s) = 1 then
458 begin
459 s := Trim(SeparateRight(Value, ':'));
460 repeat
461 t := InlineDecode(Trim(FetchEx(s, ',', '"')), cp);
462 if t <> '' then
463 FToList.Add(t);
464 until s = '';
465 Exit;
466 end;
467 if Pos('CC:', s) = 1 then
468 begin
469 s := Trim(SeparateRight(Value, ':'));
470 repeat
471 t := InlineDecode(Trim(FetchEx(s, ',', '"')), cp);
472 if t <> '' then
473 FCCList.Add(t);
474 until s = '';
475 Exit;
476 end;
477 if Pos('DATE:', s) = 1 then
478 begin
479 FDate := DecodeRfcDateTime(Trim(SeparateRight(Value, ':')));
480 Exit;
481 end;
482 if Pos('REPLY-TO:', s) = 1 then
483 begin
484 FReplyTo := InlineDecode(Trim(SeparateRight(Value, ':')), cp);
485 Exit;
486 end;
487 if Pos('MESSAGE-ID:', s) = 1 then
488 begin
489 FMessageID := GetEmailAddr(Trim(SeparateRight(Value, ':')));
490 Exit;
491 end;
492 if Pos('PRIORITY:', s) = 1 then
493 begin
494 FPri := ParsePriority(value);
495 Exit;
496 end;
497 if Pos('X-PRIORITY:', s) = 1 then
498 begin
499 FXPri := ParsePriority(value);
500 Exit;
501 end;
502 if Pos('X-MSMAIL-PRIORITY:', s) = 1 then
503 begin
504 FXmsPri := ParsePriority(value);
505 Exit;
506 end;
507 if Pos('MIME-VERSION:', s) = 1 then
508 Exit;
509 if Pos('CONTENT-TYPE:', s) = 1 then
510 Exit;
511 if Pos('CONTENT-DESCRIPTION:', s) = 1 then
512 Exit;
513 if Pos('CONTENT-DISPOSITION:', s) = 1 then
514 Exit;
515 if Pos('CONTENT-ID:', s) = 1 then
516 Exit;
517 if Pos('CONTENT-TRANSFER-ENCODING:', s) = 1 then
518 Exit;
519 Result := False;
520end;
521
522procedure TMessHeader.DecodeHeaders(const Value: TStrings);
523var
524 s: string;
525 x: Integer;
526begin
527 Clear;
528 Fpri := MP_unknown;
529 Fxpri := MP_unknown;
530 Fxmspri := MP_unknown;
531 x := 0;
532 while Value.Count > x do
533 begin
534 s := NormalizeHeader(Value, x);
535 if s = '' then
536 Break;
537 if not DecodeHeader(s) then
538 FCustomHeaders.Add(s);
539 end;
540 if Fpri <> MP_unknown then
541 FPriority := Fpri
542 else
543 if Fxpri <> MP_unknown then
544 FPriority := Fxpri
545 else
546 if Fxmspri <> MP_unknown then
547 FPriority := Fxmspri
548end;
549
550function TMessHeader.FindHeader(Value: string): string;
551var
552 n: integer;
553begin
554 Result := '';
555 for n := 0 to FCustomHeaders.Count - 1 do
556 if Pos(UpperCase(Value), UpperCase(FCustomHeaders[n])) = 1 then
557 begin
558 Result := Trim(SeparateRight(FCustomHeaders[n], ':'));
559 break;
560 end;
561end;
562
563procedure TMessHeader.FindHeaderList(Value: string; const HeaderList: TStrings);
564var
565 n: integer;
566begin
567 HeaderList.Clear;
568 for n := 0 to FCustomHeaders.Count - 1 do
569 if Pos(UpperCase(Value), UpperCase(FCustomHeaders[n])) = 1 then
570 begin
571 HeaderList.Add(Trim(SeparateRight(FCustomHeaders[n], ':')));
572 end;
573end;
574
575{==============================================================================}
576
577constructor TMimeMess.Create;
578begin
579 CreateAltHeaders(TMessHeader);
580end;
581
582constructor TMimeMess.CreateAltHeaders(HeadClass: TMessHeaderClass);
583begin
584 inherited Create;
585 FMessagePart := TMimePart.Create;
586 FLines := TStringList.Create;
587 FHeader := HeadClass.Create;
588end;
589
590destructor TMimeMess.Destroy;
591begin
592 FMessagePart.Free;
593 FHeader.Free;
594 FLines.Free;
595 inherited Destroy;
596end;
597
598{==============================================================================}
599
600procedure TMimeMess.Clear;
601begin
602 FMessagePart.Clear;
603 FLines.Clear;
604 FHeader.Clear;
605end;
606
607{==============================================================================}
608
609function TMimeMess.AddPart(const PartParent: TMimePart): TMimePart;
610begin
611 if PartParent = nil then
612 Result := FMessagePart
613 else
614 Result := PartParent.AddSubPart;
615 Result.Clear;
616end;
617
618{==============================================================================}
619
620function TMimeMess.AddPartMultipart(const MultipartType: String; const PartParent: TMimePart): TMimePart;
621begin
622 Result := AddPart(PartParent);
623 with Result do
624 begin
625 Primary := 'Multipart';
626 Secondary := MultipartType;
627 Description := 'Multipart message';
628 Boundary := GenerateBoundary;
629 EncodePartHeader;
630 end;
631end;
632
633function TMimeMess.AddPartText(const Value: TStrings; const PartParent: TMimePart): TMimepart;
634begin
635 Result := AddPart(PartParent);
636 with Result do
637 begin
638 Value.SaveToStream(DecodedLines);
639 Primary := 'text';
640 Secondary := 'plain';
641 Description := 'Message text';
642 Disposition := 'inline';
643 CharsetCode := IdealCharsetCoding(Value.Text, TargetCharset, IdealCharsets);
644 EncodingCode := ME_QUOTED_PRINTABLE;
645 EncodePart;
646 EncodePartHeader;
647 end;
648end;
649
650function TMimeMess.AddPartTextEx(const Value: TStrings; const PartParent: TMimePart;
651 PartCharset: TMimeChar; Raw: Boolean; PartEncoding: TMimeEncoding): TMimepart;
652begin
653 Result := AddPart(PartParent);
654 with Result do
655 begin
656 Value.SaveToStream(DecodedLines);
657 Primary := 'text';
658 Secondary := 'plain';
659 Description := 'Message text';
660 Disposition := 'inline';
661 CharsetCode := PartCharset;
662 EncodingCode := PartEncoding;
663 ConvertCharset := not Raw;
664 EncodePart;
665 EncodePartHeader;
666 end;
667end;
668
669function TMimeMess.AddPartHTML(const Value: TStrings; const PartParent: TMimePart): TMimepart;
670begin
671 Result := AddPart(PartParent);
672 with Result do
673 begin
674 Value.SaveToStream(DecodedLines);
675 Primary := 'text';
676 Secondary := 'html';
677 Description := 'HTML text';
678 Disposition := 'inline';
679 CharsetCode := UTF_8;
680 EncodingCode := ME_QUOTED_PRINTABLE;
681 EncodePart;
682 EncodePartHeader;
683 end;
684end;
685
686function TMimeMess.AddPartTextFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
687var
688 tmp: TStrings;
689begin
690 tmp := TStringList.Create;
691 try
692 tmp.LoadFromFile(FileName);
693 Result := AddPartText(tmp, PartParent);
694 Finally
695 tmp.Free;
696 end;
697end;
698
699function TMimeMess.AddPartHTMLFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
700var
701 tmp: TStrings;
702begin
703 tmp := TStringList.Create;
704 try
705 tmp.LoadFromFile(FileName);
706 Result := AddPartHTML(tmp, PartParent);
707 Finally
708 tmp.Free;
709 end;
710end;
711
712function TMimeMess.AddPartBinary(const Stream: TStream; const FileName: string; const PartParent: TMimePart): TMimepart;
713begin
714 Result := AddPart(PartParent);
715 Result.DecodedLines.LoadFromStream(Stream);
716 Result.MimeTypeFromExt(FileName);
717 Result.Description := 'Attached file: ' + FileName;
718 Result.Disposition := 'attachment';
719 Result.FileName := FileName;
720 Result.EncodingCode := ME_BASE64;
721 Result.EncodePart;
722 Result.EncodePartHeader;
723end;
724
725function TMimeMess.AddPartBinaryFromFile(const FileName: string; const PartParent: TMimePart): TMimepart;
726var
727 tmp: TMemoryStream;
728begin
729 tmp := TMemoryStream.Create;
730 try
731 tmp.LoadFromFile(FileName);
732 Result := AddPartBinary(tmp, ExtractFileName(FileName), PartParent);
733 finally
734 tmp.Free;
735 end;
736end;
737
738function TMimeMess.AddPartHTMLBinary(const Stream: TStream; const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
739begin
740 Result := AddPart(PartParent);
741 Result.DecodedLines.LoadFromStream(Stream);
742 Result.MimeTypeFromExt(FileName);
743 Result.Description := 'Included file: ' + FileName;
744 Result.Disposition := 'inline';
745 Result.ContentID := Cid;
746 Result.FileName := FileName;
747 Result.EncodingCode := ME_BASE64;
748 Result.EncodePart;
749 Result.EncodePartHeader;
750end;
751
752function TMimeMess.AddPartHTMLBinaryFromFile(const FileName, Cid: string; const PartParent: TMimePart): TMimepart;
753var
754 tmp: TMemoryStream;
755begin
756 tmp := TMemoryStream.Create;
757 try
758 tmp.LoadFromFile(FileName);
759 Result :=AddPartHTMLBinary(tmp, ExtractFileName(FileName), Cid, PartParent);
760 finally
761 tmp.Free;
762 end;
763end;
764
765function TMimeMess.AddPartMess(const Value: TStrings; const PartParent: TMimePart): TMimepart;
766var
767 part: Tmimepart;
768begin
769 Result := AddPart(PartParent);
770 part := AddPart(result);
771 part.lines.addstrings(Value);
772 part.DecomposeParts;
773 with Result do
774 begin
775 Primary := 'message';
776 Secondary := 'rfc822';
777 Description := 'E-mail Message';
778 EncodePart;
779 EncodePartHeader;
780 end;
781end;
782
783function TMimeMess.AddPartMessFromFile(const FileName: String; const PartParent: TMimePart): TMimepart;
784var
785 tmp: TStrings;
786begin
787 tmp := TStringList.Create;
788 try
789 tmp.LoadFromFile(FileName);
790 Result := AddPartMess(tmp, PartParent);
791 Finally
792 tmp.Free;
793 end;
794end;
795
796{==============================================================================}
797
798procedure TMimeMess.EncodeMessage;
799var
800 l: TStringList;
801 x: integer;
802begin
803 //merge headers from THeaders and header field from MessagePart
804 l := TStringList.Create;
805 try
806 FHeader.EncodeHeaders(l);
807 x := IndexByBegin('CONTENT-TYPE', FMessagePart.Headers);
808 if x >= 0 then
809 l.add(FMessagePart.Headers[x]);
810 x := IndexByBegin('CONTENT-DESCRIPTION', FMessagePart.Headers);
811 if x >= 0 then
812 l.add(FMessagePart.Headers[x]);
813 x := IndexByBegin('CONTENT-DISPOSITION', FMessagePart.Headers);
814 if x >= 0 then
815 l.add(FMessagePart.Headers[x]);
816 x := IndexByBegin('CONTENT-ID', FMessagePart.Headers);
817 if x >= 0 then
818 l.add(FMessagePart.Headers[x]);
819 x := IndexByBegin('CONTENT-TRANSFER-ENCODING', FMessagePart.Headers);
820 if x >= 0 then
821 l.add(FMessagePart.Headers[x]);
822 FMessagePart.Headers.Assign(l);
823 finally
824 l.Free;
825 end;
826 FMessagePart.ComposeParts;
827 FLines.Assign(FMessagePart.Lines);
828end;
829
830{==============================================================================}
831
832procedure TMimeMess.DecodeMessage;
833begin
834 FHeader.Clear;
835 FHeader.DecodeHeaders(FLines);
836 FMessagePart.Lines.Assign(FLines);
837 FMessagePart.DecomposeParts;
838end;
839
840{pf}
841procedure TMimeMess.DecodeMessageBinary(AHeader:TStrings; AData:TMemoryStream);
842begin
843 FHeader.Clear;
844 FLines.Clear;
845 FLines.Assign(AHeader);
846 FHeader.DecodeHeaders(FLines);
847 FMessagePart.DecomposePartsBinary(AHeader,PANSIChar(AData.Memory),PANSIChar(AData.Memory)+AData.Size);
848end;
849{/pf}
850
851end.
Note: See TracBrowser for help on using the repository browser.