Pop3DBModule.pas 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. unit Pop3DBModule;
  2. { This unit is performing all the internal data housekeeping:
  3. Mailboxes
  4. Accounts
  5. Passwords
  6. Email Adresses
  7. Most are kept in Stringlists, the Objects containing some additional data.
  8. You can easily extend this using a small database (Firebird recommended)
  9. to have the data for the users stored in a convenient way.
  10. (c)2005
  11. Jörg Meier (Bob)
  12. [email protected]
  13. }
  14. interface
  15. uses
  16. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs;
  17. // Some Globals
  18. Const
  19. MBoxFolder = 'MailBoxes\'; // Foldername for storing Mailboxes
  20. SentArchive = 'SentMails\';
  21. Type
  22. TPop3DBMod = class(TDataModule)
  23. procedure DataModuleCreate(Sender: TObject);
  24. procedure DataModuleDestroy(Sender: TObject);
  25. private
  26. { Private-Deklarationen }
  27. fMailboxList : tStringList;
  28. fEmailAddrs : tStringList;
  29. fSendQueue : tThreadList;
  30. Function AddUser(Const AUserName,APassword,AMBoxName:String):Boolean;
  31. Function AddEmailAccount(Const AEmailAddress,AUserName:String):Boolean;
  32. Procedure FillUserList;
  33. public
  34. { Public-Deklarationen }
  35. Property MailBoxList : tStringList read fMailBoxList;
  36. Property EmailAddrs : tStringList read fEmailAddrs;
  37. Property SendQueue : tThreadList read fSendQueue;
  38. Function GetSendMailCount:Integer;
  39. Function GetMailNumber:Cardinal;
  40. Function GetSendFileName(Const AMBox:String):String;
  41. Function GetRecvFileName(const AMBox: String): String;
  42. Procedure EnterToSendMail(Const AFileName:String);
  43. Function GetMBoxName(Const AUser:String):String;
  44. end;
  45. var
  46. Pop3DBMod: TPop3DBMod;
  47. Function GetValidMailBoxName(Const AUserName,APassword:String):String;
  48. Function GetMailBoxList:tStringList;
  49. implementation
  50. Uses IdGlobal;
  51. {$R *.DFM}
  52. Type
  53. tUserObject = Class(tObject)
  54. PassWord : String;
  55. MBoxName : String;
  56. Constructor Create(Const APassword,AMBoxName:String);
  57. end;
  58. { if you use a database, this can be used to sequence accesses to the DB which
  59. normally wouldn't be thread-save
  60. }
  61. Var DBSection : tIdCriticalSection;
  62. { TPop3DBMod }
  63. function GetValidMailBoxName(const AUserName,APassword: String): String;
  64. {
  65. A user is logging in. He gave us a Username together with a password.
  66. Check for a legal combination and return the path to the mailfolder
  67. if it was NOT successful, return an epty string instead.
  68. }
  69. Var Nr : Integer;
  70. This : tUserObject;
  71. begin
  72. With Pop3DBMod do
  73. begin
  74. Result := ''; // assume failure
  75. Nr := fMailBoxList.IndexOf(AUserName);
  76. If Nr < 0 then Exit; // User is unknown
  77. This := tUserObject(fMailBoxList.Objects[Nr]);
  78. If This.PassWord = APassword then Result := This.MBoxName
  79. Else Result := '';
  80. end;
  81. end;
  82. Function GetMailBoxList:tStringList;
  83. {
  84. Return a list of all known local mailboxes
  85. }
  86. Var ii : Integer;
  87. Begin
  88. Result := tStringlist.Create;
  89. Result.Duplicates := DupIgnore;
  90. With Pop3DBMod do
  91. begin
  92. for ii := 0 to fMailBoxList.Count-1 do
  93. begin
  94. Result.Add(tUserObject(fMailboxlist.Objects[ii]).MBoxName);
  95. end;
  96. end;
  97. end;
  98. procedure TPop3DBMod.DataModuleCreate(Sender: TObject);
  99. begin
  100. DBSection := tIdCriticalSection.Create;
  101. fMailBoxList := tStringList.Create;
  102. fMailboxlist.Duplicates := DupError;
  103. fMailboxlist.Sorted := True;
  104. fEmailAddrs := tStringlist.Create;
  105. fEmailAddrs.Duplicates := DupError;
  106. fEmailAddrs.Sorted := True;
  107. FillUserList;
  108. fSendQueue := tThreadList.Create;
  109. end;
  110. procedure TPop3DBMod.DataModuleDestroy(Sender: TObject);
  111. Var ii : Integer;
  112. MyUsr : tUserObject;
  113. begin
  114. // Clear MailBoxList
  115. For ii := 0 to fMailBoxList.Count-1 do
  116. begin
  117. MyUsr := tUserObject(fMailBoxList.Objects[ii]);
  118. FreeAndNil(MyUsr);
  119. fMailBoxList.Objects[ii] := nil;
  120. end;
  121. FreeAndNil(fMailBoxList);
  122. FreeAndNil(FEmailAddrs);
  123. FreeAndNil(DBSection);
  124. end;
  125. function TPop3DBMod.AddUser(const AUserName, APassword,AMBoxName: String): Boolean;
  126. { Add a user to the local system
  127. AUsername : is the account
  128. APassword : plain-text password
  129. AMBoxname : is the folder where this user's mail will be stored.
  130. actually, this folder is created below the folder where
  131. this program runs.
  132. All this information is NOT saved, it is kept in mem as long as the server lives.
  133. }
  134. Var ThisUser : tUserObject;
  135. begin
  136. Result := True; // assume all goes well
  137. try
  138. ThisUser := tUserObject.Create(APassword,AMBoxName);
  139. fMailBoxList.AddObject(AUserName,ThisUser);
  140. Except
  141. Result := False;
  142. end;
  143. end;
  144. function TPop3DBMod.AddEmailAccount(const AEmailAddress, AUserName: String): Boolean;
  145. Var Nr : Integer;
  146. begin
  147. Result := False; // Assume Error
  148. Try
  149. Nr := MailBoxList.IndexOf(AUserName);
  150. If Nr < 0 then exit; // Not found
  151. EmailAddrs.AddObject(AEmailAddress,Pointer(Nr));
  152. Result := True; // Success;
  153. except
  154. Exit;
  155. end;
  156. end;
  157. procedure TPop3DBMod.FillUserList;
  158. {
  159. Here the Users are fed into the system. Hard coded only, but it's a demo.
  160. You should again use a database and read out every information.
  161. }
  162. begin
  163. try
  164. DBSection.Enter;
  165. { first the user in the system }
  166. // AddUser(AccountName,Password,Foldername);
  167. AddUser('Thats.MySelf','Top_Secret','MyMailBox');
  168. { then the external email-address and the Username (for delivering inbound mail)}
  169. // AddEmail(Email-Address,Username)
  170. AddEmailAccount('[email protected]','Thats.MySelf');
  171. Finally
  172. DBSection.Leave;
  173. end;
  174. end;
  175. function TPop3DBMod.GetMailNumber: Cardinal;
  176. { This routine (a pretty good database-candidate as well) generates
  177. a unique ascending number
  178. }
  179. Const NumberFName = 'MailNum.Dat';
  180. Var NumberFile : File of Cardinal;
  181. FName : String;
  182. begin
  183. DBSection.Enter;
  184. Try
  185. FName := ExtractFilePath(Application.ExeName)+NumberFName;
  186. AssignFile(NumberFile,FName);
  187. If FileExists(FName) Then
  188. begin
  189. Reset(NumberFile);
  190. Read(NumberFile,Result);
  191. Inc(Result);
  192. Seek(NumberFile,0);
  193. end
  194. else begin
  195. Rewrite(NumberFile);
  196. Result := 1; // Start with one
  197. End;
  198. Write(NumberFile,Result);
  199. Finally
  200. CloseFile(NumberFile);
  201. DBSection.Leave;
  202. end;
  203. end;
  204. function TPop3DBMod.GetSendFileName(const AMBox: String): String;
  205. // Generate FileName for a mail to send
  206. begin
  207. Result := AMBox + '\'
  208. + Format('M%.8d.SNT',[GetMailNumber]);
  209. end;
  210. function TPop3DBMod.GetRecvFileName(const AMBox: String): String;
  211. // Generate FileName for a mail to send
  212. begin
  213. Result := AMBox + '\'
  214. + Format('M%.8d.RAW',[GetMailNumber]);
  215. end;
  216. function TPop3DBMod.GetSendMailCount: Integer;
  217. Var MyList : tList;
  218. begin
  219. MyList := SendQueue.LockList;
  220. Result := MyList.Count;
  221. SendQueue.UnlockList;
  222. end;
  223. procedure TPop3DBMod.EnterToSendMail(const AFileName: String);
  224. {
  225. Put the Filename to send into our Sendqueue. This is a thread-safe
  226. list, so we can put in, send and delete simultaneously.
  227. }
  228. begin
  229. SendQueue.Add(StrNew(PChar(AFileName)));
  230. end;
  231. function TPop3DBMod.GetMBoxName(const AUser: String): String;
  232. Var Nr : Integer;
  233. begin
  234. Result := '';
  235. Nr := MailBoxList.IndexOf(AUser);
  236. If Nr < 0 then exit; // Not found, could rise an Exception as well
  237. Result := tUserObject(MailBoxList.Objects[Nr]).MBoxName;
  238. end;
  239. { tUserObject }
  240. constructor tUserObject.Create(const APassword,AMBoxName: String);
  241. begin
  242. Self.PassWord := APassWord;
  243. Self.MBoxName := AMBoxName;
  244. end;
  245. end.