Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88b2549243 | ||
|
|
a1ece5258a |
+1
-1
@@ -1 +1 @@
|
||||
1.9.0
|
||||
1.10.0
|
||||
|
||||
+1
-1
@@ -47,5 +47,5 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/bablukid/cagette/issues"
|
||||
},
|
||||
"version": "1.9.0"
|
||||
"version": "1.10.0"
|
||||
}
|
||||
|
||||
+33
-20
@@ -77,10 +77,14 @@ class App extends sugoi.BaseApp {
|
||||
}
|
||||
|
||||
public static function log(t:Dynamic, ?infos:haxe.PosInfos) {
|
||||
// if (App.config.DEBUG) {
|
||||
// neko.Web.logMessage(Std.string(t)); // write in Apache error log
|
||||
// }
|
||||
neko.Web.logMessage('[${infos.fileName}:${infos.lineNumber} ${infos.className}#${infos.methodName}] ' + Std.string(t));
|
||||
var message:String = '[${infos.fileName}:${infos.lineNumber} ${infos.className}#${infos.methodName}] ';
|
||||
message += Std.string(t);
|
||||
|
||||
// trace(message);
|
||||
if (neko.Web.isModNeko)
|
||||
neko.Web.logMessage(message);
|
||||
else
|
||||
Sys.println(message);
|
||||
}
|
||||
|
||||
public function event(e:Event) {
|
||||
@@ -230,24 +234,34 @@ class App extends sugoi.BaseApp {
|
||||
}
|
||||
|
||||
public static function getMailer():sugoi.mail.IMailer {
|
||||
var mailer:sugoi.mail.IMailer = new sugoi.mail.BufferedMailer();
|
||||
var typeOfMailer = sugoi.db.Variable.get("mailer");
|
||||
App.log('type of mailer is <$typeOfMailer>');
|
||||
|
||||
if (typeOfMailer == null) {
|
||||
var msg = sugoi.i18n.Locale.texts._("Please configure the email settings in a <href='/admin/emails'>this section</a>");
|
||||
throw sugoi.ControllerAction.ErrorAction("/", msg);
|
||||
}
|
||||
|
||||
if (App.config.DEBUG) {
|
||||
App.log("DEBUGEmailer enabled => emails are written to tmp folder");
|
||||
mailer = new sugoi.mail.DebugMailer();
|
||||
} else {
|
||||
if (sugoi.db.Variable.get("mailer") == null) {
|
||||
var msg = sugoi.i18n.Locale.texts._("Please configure the email settings in a <href='/admin/emails'>this section</a>");
|
||||
throw sugoi.ControllerAction.ErrorAction("/", msg);
|
||||
}
|
||||
App.log('mailer in DEBUG mode, no deferred mail from CRON');
|
||||
|
||||
if (sugoi.db.Variable.get("mailer") == "mandrill") {
|
||||
// Buffered emails with Mandrill
|
||||
untyped mailer.defineFinalMailer("mandrill");
|
||||
} else {
|
||||
// Buffered emails with SMTP
|
||||
untyped mailer.defineFinalMailer("smtp");
|
||||
}
|
||||
var conf = {
|
||||
smtp_host: sugoi.db.Variable.get("smtp_host"),
|
||||
smtp_port: sugoi.db.Variable.getInt("smtp_port"),
|
||||
smtp_user: sugoi.db.Variable.get("smtp_user"),
|
||||
smtp_pass: sugoi.db.Variable.get("smtp_pass")
|
||||
};
|
||||
|
||||
return new sugoi.mail.SendEmailMailer().init(conf);
|
||||
}
|
||||
|
||||
var mailer:sugoi.mail.IMailer = new sugoi.mail.BufferedMailer();
|
||||
if (sugoi.db.Variable.get("mailer") == "mandrill") {
|
||||
// Buffered emails with Mandrill
|
||||
untyped mailer.defineFinalMailer("mandrill");
|
||||
} else {
|
||||
// Buffered emails with SMTP
|
||||
untyped mailer.defineFinalMailer("smtp");
|
||||
}
|
||||
return mailer;
|
||||
}
|
||||
@@ -265,7 +279,6 @@ class App extends sugoi.BaseApp {
|
||||
|
||||
App.log('about to send email with subject=<${m.getSubject()}> ...');
|
||||
getMailer().send(m, params, function(o) {});
|
||||
App.log('email from=<${m.getSender().email}>, subject=<${m.getSubject()}> successfully sent');
|
||||
}
|
||||
|
||||
public static function quickMail(to:String, subject:String, html:String, ?group:db.Amap) {
|
||||
|
||||
@@ -444,7 +444,6 @@ class Cron extends Controller {
|
||||
*/
|
||||
function sendEmailsfromBuffer() {
|
||||
App.log("Send Emails from Buffer");
|
||||
print("<h3>Send Emails from Buffer</h3>");
|
||||
|
||||
// send
|
||||
for (e in sugoi.db.BufferedMail.manager.search($sdate == null, {limit: 50, orderBy: -cdate}, false)) {
|
||||
@@ -452,8 +451,7 @@ class Cron extends Controller {
|
||||
if (e.isSent())
|
||||
continue;
|
||||
|
||||
App.log('Send Email id=${e.id} - title=${e.title}');
|
||||
print('#${e.id} - ${e.title}');
|
||||
App.log('Send Email id=#${e.id} - title=${e.title}');
|
||||
e.finallySend();
|
||||
Sys.sleep(0.1);
|
||||
}
|
||||
|
||||
@@ -82,16 +82,7 @@ class Messages extends Controller {
|
||||
var html = app.processTemplate("mail/message.mtt", {text: text, group: app.user.amap, list: getListName(listId)});
|
||||
e.setHtmlBody(html);
|
||||
|
||||
// FIXME: re-apply sendMail
|
||||
// App.sendMail(e, app.user.getAmap(), listId, app.user);
|
||||
|
||||
// Sys.command("sendemail", [
|
||||
// "-f", "no-reply@comptoirduvrac.re", "-s", "mail1.zourit.net:587", "-t", "pvincent@comptoirduvrac.re", "-bcc",
|
||||
// "pvincent974@gmail.com,pvincent974@laposte.net", "-u", subject, "-m", "alors tout va bien", "-xu", "postmaster@comptoirduvrac.re", "-xp",
|
||||
// "QqQeAPT6EpoK"
|
||||
// ]);
|
||||
|
||||
sys.io.File.saveContent('/tmp/my_file.json', "CONTENT");
|
||||
App.sendMail(e, app.user.getAmap(), listId, app.user);
|
||||
|
||||
// store message
|
||||
var lm = new db.Message();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package sugoi.db;
|
||||
|
||||
import sys.db.Types;
|
||||
import sugoi.mail.IMail;
|
||||
import sugoi.mail.IMailer;
|
||||
@@ -6,127 +7,116 @@ import sugoi.mail.IMailer;
|
||||
/**
|
||||
* DB Buffer for emails
|
||||
*/
|
||||
@:index(remoteId,sdate,cdate)
|
||||
class BufferedMail extends sys.db.Object
|
||||
{
|
||||
public var id : SId;
|
||||
@:index(remoteId, sdate, cdate)
|
||||
class BufferedMail extends sys.db.Object {
|
||||
public var id:SId;
|
||||
|
||||
//email content
|
||||
public var title : SString<256>;
|
||||
public var htmlBody : SNull<SText>;
|
||||
public var textBody : SNull<SText>;
|
||||
public var headers : SData<Map<String,String>>;
|
||||
public var sender : SData<{name:String,email:String,?userId:Int}>;
|
||||
public var recipients : SData<Array<{name:String,email:String,?userId:Int}>>;
|
||||
|
||||
//utility fields
|
||||
public var mailerType : SString<32>; //mailer used when sending for real
|
||||
public var tries : SInt; //number of times we tried to send the mail
|
||||
public var cdate : SDateTime; //creation date
|
||||
public var sdate : SNull<SDateTime>; //sent date
|
||||
public var rawStatus : SNull<SText>; //raw return from the smtp server or mandrill API
|
||||
public var status : SNull<SData<MailerResult>>; //map of emails with api/smtp results
|
||||
// email content
|
||||
public var title:SString<256>;
|
||||
public var htmlBody:SNull<SText>;
|
||||
public var textBody:SNull<SText>;
|
||||
public var headers:SData<Map<String, String>>;
|
||||
public var sender:SData<{name:String, email:String, ?userId:Int}>;
|
||||
public var recipients:SData<Array<{name:String, email:String, ?userId:Int}>>;
|
||||
|
||||
//custom datas
|
||||
public var data : SNull<SData<Dynamic>>;//custom datas
|
||||
public var remoteId : SNull<Int>; //custom remote Id (userId, groupId ...)
|
||||
// utility fields
|
||||
public var mailerType:SString<32>; // mailer used when sending for real
|
||||
public var tries:SInt; // number of times we tried to send the mail
|
||||
public var cdate:SDateTime; // creation date
|
||||
public var sdate:SNull<SDateTime>; // sent date
|
||||
public var rawStatus:SNull<SText>; // raw return from the smtp server or mandrill API
|
||||
public var status:SNull<SData<MailerResult>>; // map of emails with api/smtp results
|
||||
|
||||
|
||||
public function getMailerResultMessage(k:String):{failure:String, success:String}{
|
||||
// custom datas
|
||||
public var data:SNull<SData<Dynamic>>; // custom datas
|
||||
public var remoteId:SNull<Int>; // custom remote Id (userId, groupId ...)
|
||||
|
||||
public function getMailerResultMessage(k:String):{failure:String, success:String} {
|
||||
var t = sugoi.i18n.Locale.texts;
|
||||
var out = {failure:null, success:null};
|
||||
switch(status.get(k)){
|
||||
var out = {failure: null, success: null};
|
||||
switch (status.get(k)) {
|
||||
case tink.core.Outcome.Failure(f):
|
||||
out.failure = switch(f){
|
||||
case GenericError(e): t._("Generic error: ") + e.toString();
|
||||
case HardBounce : t._("Mailbox does not exist");
|
||||
case SoftBounce : t._("Mailbox full or blocked");
|
||||
case Spam: t._("Message considered as spam");
|
||||
case Unsub: t._("This user unsubscribed");
|
||||
case Unsigned: t._("Sender incorrect (Unsigned)");
|
||||
|
||||
out.failure = switch (f) {
|
||||
case GenericError(e): t._("Generic error: ") + e.toString();
|
||||
case HardBounce: t._("Mailbox does not exist");
|
||||
case SoftBounce: t._("Mailbox full or blocked");
|
||||
case Spam: t._("Message considered as spam");
|
||||
case Unsub: t._("This user unsubscribed");
|
||||
case Unsigned: t._("Sender incorrect (Unsigned)");
|
||||
};
|
||||
case tink.core.Outcome.Success(s):
|
||||
out.success = switch(s){
|
||||
case Sent : t._("Sent");
|
||||
case Queued : t._("Queued");
|
||||
out.success = switch (s) {
|
||||
case Sent: t._("Sent");
|
||||
case Queued: t._("Queued");
|
||||
};
|
||||
}
|
||||
return out;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function new(){
|
||||
public function new() {
|
||||
super();
|
||||
cdate = Date.now();
|
||||
tries = 0;
|
||||
}
|
||||
|
||||
public function isSent(){
|
||||
return sdate!=null;
|
||||
public function isSent() {
|
||||
return sdate != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finally really send the message
|
||||
*/
|
||||
public function finallySend():Void{
|
||||
public function finallySend():Void {
|
||||
if (isSent())
|
||||
throw "already sent";
|
||||
|
||||
if(isSent()) throw "already sent";
|
||||
|
||||
var conf = {
|
||||
smtp_host:sugoi.db.Variable.get("smtp_host"),
|
||||
smtp_port:sugoi.db.Variable.getInt("smtp_port"),
|
||||
smtp_user:sugoi.db.Variable.get("smtp_user"),
|
||||
smtp_pass:sugoi.db.Variable.get("smtp_pass")
|
||||
smtp_host: sugoi.db.Variable.get("smtp_host"),
|
||||
smtp_port: sugoi.db.Variable.getInt("smtp_port"),
|
||||
smtp_user: sugoi.db.Variable.get("smtp_user"),
|
||||
smtp_pass: sugoi.db.Variable.get("smtp_pass")
|
||||
};
|
||||
|
||||
var mailer : sugoi.mail.IMailer = switch(this.mailerType){
|
||||
App.log('choose mail from ${this.mailerType}');
|
||||
|
||||
var mailer:sugoi.mail.IMailer = switch (this.mailerType) {
|
||||
case "mandrill":
|
||||
new sugoi.mail.MandrillMailer().init(conf);
|
||||
case "smtp":
|
||||
new sugoi.mail.SmtpMailer().init(conf);
|
||||
case "debug":
|
||||
new sugoi.mail.DebugMailer();
|
||||
default :
|
||||
throw "Unknown mailer type : "+this.mailerType;
|
||||
new sugoi.mail.SendEmailMailer().init(conf);
|
||||
default:
|
||||
throw "Unknown mailer type : " + this.mailerType;
|
||||
};
|
||||
|
||||
|
||||
var m = new sugoi.mail.Mail();
|
||||
for( k in this.headers.keys() ) m.setHeader( k,headers[k] );
|
||||
for (k in this.headers.keys())
|
||||
m.setHeader(k, headers[k]);
|
||||
m.setSubject(this.title);
|
||||
for( r in recipients) m.setRecipient(r.email,r.name,r.userId);
|
||||
m.setSender(sender.email,sender.name,sender.userId);
|
||||
for (r in recipients)
|
||||
m.setRecipient(r.email, r.name, r.userId);
|
||||
m.setSender(sender.email, sender.name, sender.userId);
|
||||
m.setHtmlBody(this.htmlBody);
|
||||
m.setTextBody(this.textBody);
|
||||
|
||||
|
||||
this.lock();
|
||||
this.tries++;
|
||||
|
||||
try{
|
||||
mailer.send(m,null,afterSendCb);
|
||||
try {
|
||||
mailer.send(m, null, afterSendCb);
|
||||
this.sdate = Date.now();
|
||||
this.rawStatus = null;
|
||||
}catch(e:Dynamic){
|
||||
} catch (e:Dynamic) {
|
||||
this.sdate = null;
|
||||
this.rawStatus = Std.string(e);
|
||||
// App.current.logError( Std.string(e) );
|
||||
}
|
||||
|
||||
this.update();
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
|
||||
function afterSendCb(status:MailerResult){
|
||||
//App.current.logError(status);
|
||||
function afterSendCb(status:MailerResult) {
|
||||
// App.current.logError(status);
|
||||
this.status = status;
|
||||
this.update();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
package sugoi.mail;
|
||||
|
||||
import sugoi.mail.IMail;
|
||||
import sugoi.mail.IMailer;
|
||||
|
||||
@@ -6,23 +7,21 @@ import sugoi.mail.IMailer;
|
||||
* Manage an email buffer in a table before sending them
|
||||
* @author fbarbut
|
||||
*/
|
||||
class BufferedMailer implements IMailer
|
||||
{
|
||||
var conf : Dynamic;
|
||||
var type : String;
|
||||
class BufferedMailer implements IMailer {
|
||||
var conf:Dynamic;
|
||||
var type:String;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function init(?c:Dynamic):IMailer{
|
||||
|
||||
public function init(?c:Dynamic):IMailer {
|
||||
return this;
|
||||
}
|
||||
|
||||
public function defineFinalMailer(type:String){
|
||||
public function defineFinalMailer(type:String) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public function send(m:sugoi.mail.IMail,?params:Dynamic,?callback:MailerResult->Void):Void{
|
||||
|
||||
public function send(m:sugoi.mail.IMail, ?params:Dynamic, ?callback:MailerResult->Void):Void {
|
||||
var bm = new sugoi.db.BufferedMail();
|
||||
bm.headers = m.getHeaders();
|
||||
bm.title = m.getTitle();
|
||||
@@ -30,32 +29,28 @@ class BufferedMailer implements IMailer
|
||||
bm.textBody = m.getTextBody();
|
||||
bm.recipients = m.getRecipients();
|
||||
bm.sender = m.getSender();
|
||||
|
||||
|
||||
bm.mailerType = this.type;
|
||||
|
||||
//custom params
|
||||
if(params!=null){
|
||||
|
||||
// custom params
|
||||
if (params != null) {
|
||||
bm.data = params;
|
||||
if(Reflect.hasField(params,"remoteId")){
|
||||
bm.remoteId = Reflect.getProperty(params,"remoteId");
|
||||
if (Reflect.hasField(params, "remoteId")) {
|
||||
bm.remoteId = Reflect.getProperty(params, "remoteId");
|
||||
}
|
||||
}
|
||||
|
||||
//set sending status as "queued"
|
||||
}
|
||||
|
||||
// set sending status as "queued"
|
||||
var map = new MailerResult();
|
||||
for( r in m.getRecipients() ){
|
||||
map.set( r.email , Success(Queued) );
|
||||
for (r in m.getRecipients()) {
|
||||
map.set(r.email, Success(Queued));
|
||||
}
|
||||
|
||||
bm.status = map;
|
||||
bm.insert();
|
||||
|
||||
if(callback!=null) callback(map);
|
||||
|
||||
App.log('email from=<${m.getSender().email}>, subject=<${m.getSubject()}> buffered, waiting for cron to be further processed');
|
||||
if (callback != null)
|
||||
callback(map);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package sugoi.mail;
|
||||
|
||||
import tink.core.Future;
|
||||
import tink.core.Noise;
|
||||
import sugoi.mail.IMailer;
|
||||
import smtpmailer.Address;
|
||||
|
||||
typedef SmtpInfo = {
|
||||
host:String,
|
||||
port:Int,
|
||||
auth:{
|
||||
username:String, password:String
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send emails thru OS command `sendemail`
|
||||
* requires: `apt install sendemail libio-socket-ssl-perl libnet-ssleay-perl`
|
||||
*/
|
||||
class SendEmailMailer implements IMailer {
|
||||
var m:SmtpInfo;
|
||||
|
||||
public function new() {}
|
||||
|
||||
public function init(?conf:{
|
||||
smtp_host:String,
|
||||
smtp_port:Int,
|
||||
smtp_user:String,
|
||||
smtp_pass:String
|
||||
}):IMailer {
|
||||
var mailer:SendEmailMailer = new SendEmailMailer();
|
||||
mailer.m = {
|
||||
host: conf.smtp_host,
|
||||
port: conf.smtp_port,
|
||||
auth: {
|
||||
username: conf.smtp_user,
|
||||
password: conf.smtp_pass
|
||||
}
|
||||
};
|
||||
return mailer;
|
||||
}
|
||||
|
||||
public function send(e:sugoi.mail.IMail, ?params:Dynamic, ?callback:MailerResult->Void) {
|
||||
var mailServer = "mail1.zourit.net";
|
||||
var mailPort = 587;
|
||||
|
||||
var fromName = "John Doe";
|
||||
var fromEmail = "no-reply@comptoirduvrac.re";
|
||||
|
||||
var args = [
|
||||
"-f",
|
||||
'${fromName} <${fromEmail}>',
|
||||
"-s",
|
||||
"mail1.zourit.net:587",
|
||||
"-t",
|
||||
"pvincent@comptoirduvrac.re",
|
||||
// "-bcc", "pvincent974@gmail.com,pvincent974@laposte.net",
|
||||
"-u",
|
||||
e.getSubject(),
|
||||
"-m",
|
||||
"alors tout va bien",
|
||||
"-xu",
|
||||
"postmaster@comptoirduvrac.re",
|
||||
"-xp",
|
||||
"QqQeAPT6EpoK"
|
||||
];
|
||||
|
||||
App.log('args=${args.join(" ")}');
|
||||
|
||||
var exitCode = Sys.command("sendemail", args);
|
||||
// var exitCode = 0;
|
||||
|
||||
if (exitCode == 0)
|
||||
App.log('email from="${e.getSender().name} <${e.getSender().email}"> subject=<${e.getSubject()}> successfully sent');
|
||||
else
|
||||
App.log('ERROR: email from="${e.getSender().name} <${e.getSender().email}"> subject=<${e.getSubject()}> cannot be sent');
|
||||
|
||||
// sys.io.File.saveContent('/tmp/my_file.json', "CONTENT");
|
||||
|
||||
// var surprise = m.send({
|
||||
// subject: e.getSubject(),
|
||||
// from: new Address({address: e.getSender().email}),
|
||||
// to: Lambda.array(Lambda.map(e.getRecipients(), function(x) return new Address({address: x.email}))),
|
||||
// headers: e.getHeaders(),
|
||||
// content: {
|
||||
// text: e.getTextBody(),
|
||||
// html: e.getHtmlBody()
|
||||
// }
|
||||
// });
|
||||
|
||||
if (callback != null) {
|
||||
var map = new MailerResult();
|
||||
if (exitCode == 0)
|
||||
map.set("*", Success(Sent));
|
||||
else
|
||||
map.set("*", Failure(HardBounce));
|
||||
callback(map);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user