1 //Written in the D programming language
2 /*
3  * Code for writing IMF.
4  *
5  * Copyright (C) 2014 Jaypha
6  *
7  * Distributed under the Boost Software License, Version 1.0.
8  * (See http://www.boost.org/LICENSE_1_0.txt)
9  *
10  * Authors: Jason den Dulk
11  */
12 
13 module jaypha.inet.imf.writing;
14 
15 public import jaypha.inet.mime.header;
16 
17 import std.array;
18 import std.string;
19 
20 enum ImfMaxLineLength = 998;
21 enum ImfRecLineLength = 78;
22 
23 //-----------------------------------------------------------------------------
24 // Mailbox type used in address based headers (from, to, cc, etc)
25 
26 struct Mailbox
27 {
28   string address;
29   string name;
30   @property string asString()
31   { 
32     if (name.empty) return address;
33     else return name ~ " <" ~ address ~ ">";
34   }
35 }
36 
37 
38 //-----------------------------------------------------------------------------
39 // Performs folding to keep lines to a certian maximum length.
40 
41 string imfFold(string content, ulong additional, out ulong lastLineLength)
42 {
43   auto a = appender!string();
44 
45   while (content.length+additional > ImfMaxLineLength)
46   {
47     auto i = lastIndexOf(content[0..ImfMaxLineLength-additional],' ');
48     assert(i != 0);
49 
50     a.put(content[0..i]);
51     a.put(MimeEoln);
52     content = content[i..$];
53     additional = 0;
54   }
55   a.put(content);
56   lastLineLength = content.length;
57 
58   return a.data;
59 }
60 
61 //-----------------------------------------------------------------------------
62 // Standard function for unstructured headers.
63 
64 MimeHeader unstructuredHeader(string name, string fieldBody)
65 {
66   MimeHeader header;
67   header.name = name;
68   ulong len;
69 
70   if (name.length + fieldBody.length + 1 > ImfMaxLineLength)
71     header.fieldBody = imfFold(fieldBody,name.length+1, len);
72   else
73     header.fieldBody = fieldBody;
74   return header;
75 }
76 
77 //-----------------------------------------------------------------------------
78 // Standard function for address (from,to,cc,bcc) headers.
79 
80 MimeHeader addressHeader(string name, Mailbox[] addresses)
81 {
82   MimeHeader header;
83   header.name = name;
84 
85   string[] list;
86   ulong runningLength = name.length+1;
87   foreach (r;addresses)
88   {
89     string n = " ";
90     n ~= r.asString;
91 
92     if (runningLength + n.length > ImfMaxLineLength)
93     {
94       runningLength = -2;
95       n = MimeEoln ~ n;
96     }
97     list ~= n;
98     runningLength += n.length+1;
99   }
100   header.fieldBody = list.join(",");
101   return header;
102 }