/src/yolk-email-composer.adb

http://github.com/ThomasLocke/yolk · Ada · 412 lines · 288 code · 60 blank · 64 comment · 8 complexity · 5bf35217b073d8bb773fd93c1db159dc MD5 · raw file

  1. -------------------------------------------------------------------------------
  2. -- --
  3. -- Copyright (C) 2010-, Thomas ¸cke --
  4. -- --
  5. -- This library is free software; you can redistribute it and/or modify --
  6. -- it under terms of the GNU General Public License as published by the --
  7. -- Free Software Foundation; either version 3, or (at your option) any --
  8. -- later version. This library is distributed in the hope that it will be --
  9. -- useful, but WITHOUT ANY WARRANTY; without even the implied warranty of --
  10. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. --
  11. -- --
  12. -- As a special exception under Section 7 of GPL version 3, you are --
  13. -- granted additional permissions described in the GCC Runtime Library --
  14. -- Exception, version 3.1, as published by the Free Software Foundation. --
  15. -- --
  16. -- You should have received a copy of the GNU General Public License and --
  17. -- a copy of the GCC Runtime Library Exception along with this program; --
  18. -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
  19. -- <http://www.gnu.org/licenses/>. --
  20. -- --
  21. -------------------------------------------------------------------------------
  22. with AWS.SMTP.Client;
  23. with GNATCOLL.Email.Utils;
  24. package body Yolk.Email.Composer is
  25. -------------------------
  26. -- Add_Custom_Header --
  27. -------------------------
  28. procedure Add_Custom_Header
  29. (ES : in out Structure;
  30. Name : in String;
  31. Value : in String;
  32. Charset : in Character_Set := US_ASCII)
  33. is
  34. New_Header : Header_Data;
  35. begin
  36. New_Header.Charset := Charset;
  37. New_Header.Name := U (Name);
  38. New_Header.Value := U (Value);
  39. ES.Custom_Headers.Append (New_Header);
  40. end Add_Custom_Header;
  41. ---------------------------
  42. -- Add_File_Attachment --
  43. ---------------------------
  44. procedure Add_File_Attachment
  45. (ES : in out Structure;
  46. Path_To_File : in String;
  47. Charset : in Character_Set := US_ASCII)
  48. is
  49. New_Attachment : Attachment_Data;
  50. begin
  51. New_Attachment.Charset := Charset;
  52. New_Attachment.Path_To_File := U (Path_To_File);
  53. ES.Attachment_List.Append (New_Attachment);
  54. ES.Has_Attachment := True;
  55. end Add_File_Attachment;
  56. ----------------
  57. -- Add_From --
  58. ----------------
  59. procedure Add_From
  60. (ES : in out Structure;
  61. Address : in String;
  62. Name : in String := "";
  63. Charset : in Character_Set := US_ASCII)
  64. is
  65. New_From : Email_Data;
  66. begin
  67. New_From.Address := U (Address);
  68. New_From.Charset := Charset;
  69. New_From.Name := U (Name);
  70. ES.From_List.Append (New_Item => New_From);
  71. end Add_From;
  72. ---------------------
  73. -- Add_Recipient --
  74. ---------------------
  75. procedure Add_Recipient
  76. (ES : in out Structure;
  77. Address : in String;
  78. Name : in String := "";
  79. Kind : in Recipient_Kind := To;
  80. Charset : in Character_Set := US_ASCII)
  81. is
  82. New_Recipient : Email_Data;
  83. begin
  84. New_Recipient.Address := U (Address);
  85. New_Recipient.Charset := Charset;
  86. New_Recipient.Name := U (Name);
  87. case Kind is
  88. when Bcc =>
  89. ES.Bcc_List.Append (New_Item => New_Recipient);
  90. when Cc =>
  91. ES.Cc_List.Append (New_Item => New_Recipient);
  92. when To =>
  93. ES.To_List.Append (New_Item => New_Recipient);
  94. end case;
  95. end Add_Recipient;
  96. --------------------
  97. -- Add_Reply_To --
  98. --------------------
  99. procedure Add_Reply_To
  100. (ES : in out Structure;
  101. Address : in String;
  102. Name : in String := "";
  103. Charset : in Character_Set := US_ASCII)
  104. is
  105. New_Reply_To : Email_Data;
  106. begin
  107. New_Reply_To.Address := U (Address);
  108. New_Reply_To.Charset := Charset;
  109. New_Reply_To.Name := U (Name);
  110. ES.Reply_To_List.Append (New_Item => New_Reply_To);
  111. end Add_Reply_To;
  112. -----------------------
  113. -- Add_SMTP_Server --
  114. -----------------------
  115. procedure Add_SMTP_Server
  116. (ES : in out Structure;
  117. Host : in String;
  118. Port : in Positive := 25)
  119. is
  120. New_SMTP : SMTP_Server;
  121. begin
  122. New_SMTP.Host := U (Host);
  123. New_SMTP.Port := Port;
  124. ES.SMTP_List.Append (New_Item => New_SMTP);
  125. end Add_SMTP_Server;
  126. ---------------
  127. -- Is_Send --
  128. ---------------
  129. function Is_Send
  130. (ES : in Structure)
  131. return Boolean
  132. is
  133. begin
  134. return ES.Email_Is_Sent;
  135. end Is_Send;
  136. ------------
  137. -- Send --
  138. ------------
  139. procedure Send
  140. (ES : in out Structure)
  141. is
  142. US : Unbounded_String;
  143. begin
  144. Set_Type_Of_Email (ES => ES);
  145. case ES.Type_Of_Email is
  146. when Text =>
  147. Generate_Text_Email (ES);
  148. when Text_With_Attachment =>
  149. Generate_Text_With_Attachment_Email (ES);
  150. when Text_And_HTML =>
  151. Generate_Text_And_HTML_Email (ES);
  152. when Text_And_HTML_With_Attachment =>
  153. Generate_Text_And_HTML_With_Attachment_Email (ES);
  154. end case;
  155. if ES.SMTP_List.Is_Empty then
  156. raise No_SMTP_Host_Set;
  157. end if;
  158. GNATCOLL.Email.To_String (Msg => ES.Composed_Message,
  159. Result => US);
  160. Do_The_Actual_Sending :
  161. declare
  162. From : AWS.SMTP.E_Mail_Data;
  163. To_Count : Natural := Natural (ES.Bcc_List.Length) +
  164. Natural (ES.Cc_List.Length) + Natural (ES.To_List.Length);
  165. Recipients : AWS.SMTP.Recipients (1 .. To_Count);
  166. Server : AWS.SMTP.Receiver;
  167. Server_Failure : Boolean := False;
  168. Status : AWS.SMTP.Status;
  169. begin
  170. if ES.Sender.Address /= Null_Unbounded_String then
  171. From := AWS.SMTP.E_Mail (Name => "",
  172. Address => To_String (ES.Sender.Address));
  173. else
  174. From := AWS.SMTP.E_Mail
  175. (Name => "",
  176. Address => To_String (ES.From_List.First_Element.Address));
  177. end if;
  178. for i in ES.Bcc_List.First_Index .. ES.Bcc_List.Last_Index loop
  179. Recipients (To_Count) := AWS.SMTP.E_Mail
  180. (Name => "",
  181. Address => To_String (ES.Bcc_List.Element (i).Address));
  182. To_Count := To_Count - 1;
  183. end loop;
  184. for i in ES.Cc_List.First_Index .. ES.Cc_List.Last_Index loop
  185. Recipients (To_Count) := AWS.SMTP.E_Mail
  186. (Name => "",
  187. Address => To_String (ES.Cc_List.Element (i).Address));
  188. To_Count := To_Count - 1;
  189. end loop;
  190. for i in ES.To_List.First_Index .. ES.To_List.Last_Index loop
  191. Recipients (To_Count) := AWS.SMTP.E_Mail
  192. (Name => "",
  193. Address => To_String (ES.To_List.Element (i).Address));
  194. To_Count := To_Count - 1;
  195. end loop;
  196. for i in ES.SMTP_List.First_Index .. ES.SMTP_List.Last_Index loop
  197. Server := AWS.SMTP.Client.Initialize
  198. (Server_Name => To_String (ES.SMTP_List.Element (i).Host),
  199. Port => ES.SMTP_List.Element (i).Port);
  200. declare
  201. begin
  202. AWS.SMTP.Client.Send (Server => Server,
  203. From => From,
  204. To => Recipients,
  205. Source => To_String (US),
  206. Status => Status);
  207. exception
  208. when others =>
  209. Server_Failure := True;
  210. end;
  211. if Server_Failure then
  212. -- Reset Server_Failure
  213. Server_Failure := False;
  214. else
  215. if AWS.SMTP.Is_Ok (Status => Status) then
  216. ES.Email_Is_Sent := True;
  217. exit;
  218. end if;
  219. end if;
  220. end loop;
  221. end Do_The_Actual_Sending;
  222. end Send;
  223. ------------
  224. -- Send --
  225. ------------
  226. procedure Send
  227. (ES : in out Structure;
  228. From_Address : in String;
  229. From_Name : in String := "";
  230. To_Address : in String;
  231. To_Name : in String := "";
  232. Subject : in String;
  233. Text_Part : in String;
  234. SMTP_Server : in String := "localhost";
  235. SMTP_Port : in Positive := 25;
  236. Charset : in Character_Set := US_ASCII)
  237. is
  238. begin
  239. Add_From (ES => ES,
  240. Address => From_Address,
  241. Name => From_Name,
  242. Charset => Charset);
  243. Add_Recipient (ES => ES,
  244. Address => To_Address,
  245. Name => To_Name,
  246. Kind => To,
  247. Charset => Charset);
  248. Set_Subject (ES => ES,
  249. Subject => Subject,
  250. Charset => Charset);
  251. Set_Text_Part (ES => ES,
  252. Part => Text_Part,
  253. Charset => Charset);
  254. Add_SMTP_Server (ES => ES,
  255. Host => SMTP_Server,
  256. Port => SMTP_Port);
  257. Send (ES => ES);
  258. end Send;
  259. ------------
  260. -- Send --
  261. ------------
  262. procedure Send
  263. (ES : in out Structure;
  264. From_Address : in String;
  265. From_Name : in String := "";
  266. To_Address : in String;
  267. To_Name : in String := "";
  268. Subject : in String;
  269. Text_Part : in String;
  270. HTML_Part : in String;
  271. SMTP_Server : in String := "localhost";
  272. SMTP_Port : in Positive := 25;
  273. Charset : in Character_Set := US_ASCII)
  274. is
  275. begin
  276. Set_HTML_Part (ES => ES,
  277. Part => HTML_Part,
  278. Charset => Charset);
  279. Send (ES => ES,
  280. From_Address => From_Address,
  281. From_Name => From_Name,
  282. To_Address => To_Address,
  283. To_Name => To_Name,
  284. Subject => Subject,
  285. Text_Part => Text_Part,
  286. SMTP_Server => SMTP_Server,
  287. SMTP_Port => SMTP_Port,
  288. Charset => Charset);
  289. end Send;
  290. ---------------------
  291. -- Set_HTML_Part --
  292. ---------------------
  293. procedure Set_HTML_Part
  294. (ES : in out Structure;
  295. Part : in String;
  296. Charset : in Character_Set := US_ASCII)
  297. is
  298. use GNATCOLL.Email.Utils;
  299. US : Unbounded_String;
  300. begin
  301. Encode (Str => Part,
  302. Charset => Get_Charset (Charset => Charset),
  303. Result => US);
  304. ES.HTML_Part.Content := US;
  305. ES.HTML_Part.Charset := Charset;
  306. ES.Has_HTML_Part := True;
  307. end Set_HTML_Part;
  308. ------------------
  309. -- Set_Sender --
  310. ------------------
  311. procedure Set_Sender
  312. (ES : in out Structure;
  313. Address : in String;
  314. Name : in String := "";
  315. Charset : in Character_Set := US_ASCII)
  316. is
  317. begin
  318. ES.Sender.Address := U (Address);
  319. ES.Sender.Charset := Charset;
  320. ES.Sender.Name := U (Name);
  321. end Set_Sender;
  322. -------------------
  323. -- Set_Subject --
  324. -------------------
  325. procedure Set_Subject
  326. (ES : in out Structure;
  327. Subject : in String;
  328. Charset : in Character_Set := US_ASCII)
  329. is
  330. begin
  331. ES.Subject.Content := U (Subject);
  332. ES.Subject.Charset := Charset;
  333. end Set_Subject;
  334. ---------------------
  335. -- Set_Text_Part --
  336. ---------------------
  337. procedure Set_Text_Part
  338. (ES : in out Structure;
  339. Part : in String;
  340. Charset : in Character_Set := US_ASCII)
  341. is
  342. use GNATCOLL.Email.Utils;
  343. US : Unbounded_String;
  344. begin
  345. Encode (Str => Part,
  346. Charset => Get_Charset (Charset => Charset),
  347. Result => US);
  348. ES.Text_Part.Content := US;
  349. ES.Text_Part.Charset := Charset;
  350. ES.Has_Text_Part := True;
  351. end Set_Text_Part;
  352. end Yolk.Email.Composer;