I am using Zend_Mail_Storage_Imap library to retrieve e-mails from IMAP.
$mail = new Zend_Mail_Storage_Imap(array('connection details'));
foreach($mail as $message)
{
if($message->date > $myDesiredDate)
{
//do stuff
}else{
continue;
}
This code retrieves all the mails with the oldest mail retrieved first. The variable $myDesiredDate is the date/time, mails beyond which are not needed. Is there a way to skip the retrieval of all the mails and check each mail's date one by one? If not, can I reverse the $mail object to get the latest email at the top ?
UPDATE: I have now modified the code a little, to start from the latest mail and checking the date time of the current mail. The moment I encounter an email with the time beyond which I don't want to parse emails, I break the loop.
//time upto which I want to fetch emails (in seconds from current time)
$time = 3600;
$mail = new Zend_Mail_Storage_Imap(array('connection details'));
//get total number of messages
$total = $mail->countMessages()
//loop through the mails, starting from the latest mail
while($total>0)
{
$mailTime = strtotime(substr($mail->getMessage($total)->date,0,strlen($mail->getMessage($total)->date)-6));
//check if the email was received before the time limit
if($mailTime < (time()-$time))
break;
else
//do my thing
$total--;
}
//close mail connection
$mail->close();
The only thing that I am concerned here is, whether I shall get the mails in the correct order or not, if I start from mail count to 0 ?
Since, my code is working absolutely fine, I shall include this as an answer (quick and dirty).I now start from the latest mail and check the date time of the current mail. The moment I encounter an email with the time beyond which I don't want to parse emails, I break the loop.
//time upto which I want to fetch emails (in seconds from current time)
$time = 3600;
$mail = new Zend_Mail_Storage_Imap(array('connection details'));
//get total number of messages
$total = $mail->countMessages()
//loop through the mails, starting from the latest mail
while($total>0)
{
$mailTime = strtotime(substr($mail->getMessage($total)->date,0,strlen($mail->getMessage($total)->date)-6));
//check if the email was received before the time limit
if($mailTime < (time()-$time))
break;
else
//do my thing
$total--;
}
//close mail connection
$mail->close();
Related
My script at G AppsScript ran more often than the trigger is set for.
The purpose of the script is to check Gmail inbox every hour and if an automated email was not delivered - alert a slack channel.
There is an automation that delivers email to the Gmail address every hour, Gmail rules add a label to the emails. The script checks for the label, if found - the label is removed, the email is marked as read. When there is no label - webhook url is triggered to send an alert.
However, now the code was executed 3 times within an hour instead of 1 time as trigger is set. This resulted in 2 notifications to slack.
Could someone help to understand what is wrong?
trigger
executions
function parseEmailByLabel() {
var gmailLabelName = "ParseThis",
externalHandlerScript = "https://hooks.slack.com/workflows/T1234",
gmailLabelObject = GmailApp.getUserLabelByName(gmailLabelName),
threads = gmailLabelObject.getThreads(),
messages,
message,
params,
response;
if (threads != "") {
for (var i = 0; i < threads.length; i++) {
messages = threads[i].getMessages();
for (var j = 0; j < messages.length; j++) {
message = messages[j];
message.markRead();
}
threads[i].removeLabel(gmailLabelObject);
}
} else if (threads == "") {
params = {
'method': 'post',
};
response = UrlFetchApp.fetch(externalHandlerScript, params).getContentText();
Logger.log(response);
}
}
You may have created more than one trigger. You may check here:
https://script.google.com/home/triggers
I am using below code to access an email template and send mail. It works fine except it took long time (30 to 60 mins) to send mail after execution of code. I don't know how to solve this issue? Suggest any solution!!Thanks.
sen_mail.py
#api.multi
def send_email(self,invoice_id):
invoice_data = self.env['account.invoice'].browse(invoice_id)
email_template_obj = self.env['email.template']
template_id = self.env.ref('multi_db.email_template_subscription_invoice', False)
if template_id:
values = email_template_obj.generate_email(template_id.id,invoice_id)
values['subject'] = 'Invoice for AMS registration'
values['email_to'] = invoice_data.partner_id.email
values['partner_to'] = invoice_data.partner_id
mail_obj = self.env['mail.mail']
msg_id = mail_obj.create(values)
if msg_id:
mail_obj.send([msg_id])
return True
Finally got solution.
I have changed Interval Number and Interval Unit in Settings -> Technical -> Automation -> Scheduled Actions.
Kabir
Yes sure you can increase email frequency to send email faster from outgoing email queue but if you want to send email immediately without waiting then yon also use below code alternatively:
#api.multi
def send_email(self,invoice_id):
invoice_data = self.env['account.invoice'].browse(invoice_id)
email_template_obj = self.env['email.template']
template_id = self.env.ref('multi_db.email_template_subscription_invoice', False)
if template_id:
template_id.send_mail(invoice_id, force_send=False, raise_exception=False)
return True
This will send email without waiting.
Bests
My application uses an Exchange SMTP server for sending emails. At present we don't have any message queuing in our architecture and emails are sent as part of the HTTP request/response cycle.
Occasionally the Exchange server has issues and times out while the email is sending, and as a result the email doesn't send. Sometimes, Cake recognizes the time out and throws an exception. The application code can catch the exception and report to the user that something went wrong.
However, on other occasions PHP hits its maximum execution time before Cake can throw the exception and so the user just gets an error 500 with no useful information as to what happened.
In an effort to combat this, I overwrote CakeEmail::send() in a custom class CustomEmail (extending CakeEmail) as follows:
public function send($content = null)
{
//get PHP and email timeout values
$phpTimeout = ini_get("max_execution_time");
//if $this->_transportClass is debug, just invoke parent::send() and return
if (!$this->_transportClass instanceof SmtpTransport) {
return parent::send($content);
}
$cfg = $this->_transportClass->config();
$emailTimeout = isset($cfg["timeout"]) && $cfg["timeout"] ? $cfg["timeout"] : 30;
//if PHP max execution time is set (and isn't 0), set it to the email timeout plus 1 second; this should mean the SMTP server should always time out before PHP does
if ($phpTimeout) {
set_time_limit($emailTimeout + 1);
}
//send email
$send = parent::send($content);
//reset PHP timeout to previous value
set_time_limit($phpTimeout);
return $send;
}
However, this isn't alwayus successful and I have had a few instances of this:
Fatal Error: Maximum execution time of 31 seconds exceeded in [C:\path\app\Vendor\pear-pear.cakephp.org\CakePHP\Cake\Network\CakeSocket.php, line 303]
CakeSocket.php line 303 is the $buffer = fread()... line from this CakeSocket::read():
public function read($length = 1024) {
if (!$this->connected) {
if (!$this->connect()) {
return false;
}
}
if (!feof($this->connection)) {
$buffer = fread($this->connection, $length);
$info = stream_get_meta_data($this->connection);
if ($info['timed_out']) {
$this->setLastError(E_WARNING, __d('cake_dev', 'Connection timed out'));
return false;
}
return $buffer;
}
return false;
}
Any ideas?
The problem lies here:
//if PHP max execution time is set (and isn't 0), set it to the email timeout plus 1 second; this should mean the SMTP server should always time out before PHP does
if ($phpTimeout) {
set_time_limit($emailTimeout + 1);
}
In some places in my code I was increasing max time out to more than 30 seconds, but the email timeout was still only 30. This code reverted the PHP timeout to 31 seconds, and I'm guessing other stuff was happening before the email started to send which caused issues.
Fixed code:
//if PHP max execution time is set (and isn't 0), set it to the email timeout plus 1 second; this should mean the SMTP server should always time out before PHP does
if ($phpTimeout && $phpTimeout <= $emailTimeout) {
set_time_limit($emailTimeout + 1);
}
The following code listens for an incoming sms, takes all the spaces out of the sms then emails the edited sms. Everything works fine, except that the app fails to send an email. Can anyone see what I am doing wrong and help me?
new Thread() {
public void run() {
try {
DatagramConnection _dc =
(DatagramConnection)Connector.open("sms://");
for(;;) { //'For-Loop' used to listen continously for incoming sms's
Datagram d = _dc.newDatagram(_dc.getMaximumLength());
_dc.receive(d); //The sms is received
byte[] bytes = d.getData();
String address = d.getAddress(); //The address of the sms is put on a string.
String msg = new String(bytes); //The body of the sms is put on a string.
String msg2 = (replaceAll(msg, " ","")) ; //
Store store = Session.getDefaultInstance().getStore();
Folder[] folders = store.list(Folder.SENT);
Folder sentfolder = folders[0]; //Retrieve the sent folder
Message in = new Message(sentfolder);
Address recipients[] = new Address[1];
recipients[0]= new Address("me#yahoo.com", "user");
in.addRecipients(Message.RecipientType.TO, recipients);
in.setSubject("Incoming SMS"); //The subject of the message is added
in.setContent("You have just received an SMS from: " + address + "/n" + "Message: " + msg2); //Here the body of the message is formed
in.setPriority(Message.Priority.HIGH); //The priority of the message is set.
Transport.send(in); //The message is sent
in.setFlag(Message.Flag.OPENED, true);
Folder folder = in.getFolder(); //The message is deleted from the sent folder
folder.deleteMessage(in);
}
}catch (Exception me) { //All Exceptions are caught
}
}
};
public static String replaceAll(String front, String pattern, String back) {
if (front == null)
return "";
StringBuffer sb = new StringBuffer(); //A StringBufffer is created
int idx = -1;
int patIdx = 0;
while ((idx = front.indexOf(pattern, patIdx)) != -1) {
sb.append(front.substring(patIdx, idx));
sb.append(back);
patIdx = idx + pattern.length();
}
sb.append(front.substring(patIdx));
return sb.toString();
}
Thanks
This isn't really an answer to the problem, just an elaboration on my comment above, that might help.
Make sure do something in your exception catch block, so that problems in the code don't go unnoticed. It's possible that your code is not encountering any exceptions, but in order for us to help, we need to try to eliminate potential problems, and since you say the code isn't working, but you have an empty exception handler, that's an easy area to fix first.
the simplest handler is just:
try {
// try sending sms here
} catch (Exception e) {
e.printStackTrace();
}
If you can run this in the debugger (which I highly suggest), then you can now put a breakpoint on the e.printStackTrace() line, and see if it ever gets hit. If it does, inspect the value of e and tell us what it is.
Normally, in my programs, I don't actually use e.printStackTrace() in catch handlers, but I have a logging class that takes strings, and maybe a log level (e.g. info, warning, error, verbose), and writes to a log file. The log file can be attached to emails the users send to tech support, or can be disabled for production if you only want to use the feature while developing.
Anyway, start with a simple printStackTrace() and see if it ever gets hit. Then, report back.
Edit: from the symptoms you describe in the comments after your question, it seems like it's a possibility that
String msg2 = (replaceAll(msg, " ","")) ; //
is throwing an exception, and therefore never letting you get to where you'd send the email. I can't see anything wrong with your implementation of replaceAll() upon initial inspection, but that might be a place to look. Has that implementation been thoroughly unit-tested?
Also, I think you have a "/n" in your code where you probably want a "\n", right?
We're using Amazon SES to send emails, and it says our max send rate is 5 per second.
What happens if we send more than 5 per second? Do they queue or are they rejected?
We have a mailing list that has over 1,000 people on it and they all attempt to send all in one go (and we are approved to use Amazon SES for this purpose).
Here's the code I'm using to send the email:
namespace Amazon
{
public class Emailer
{
/// <summary>
/// Send an email using the Amazon SES service
/// </summary>
public static void SendEmail(String from, String To, String Subject, String HTML = null, String emailReplyTo = null, String returnPath = null)
{
try
{
List<String> to
= To
.Replace(", ", ",")
.Split(',')
.ToList();
var destination = new Destination();
destination.WithToAddresses(to);
var subject = new Content();
subject.WithCharset("UTF-8");
subject.WithData(Subject);
var html = new Content();
html.WithCharset("UTF-8");
html.WithData(HTML);
var body = new Body();
body.WithHtml(html);
var message = new Message();
message.WithBody(body);
message.WithSubject(subject);
var ses = AWSClientFactory.CreateAmazonSimpleEmailServiceClient("xxx", "xxx");
var request = new SendEmailRequest();
request.WithDestination(destination);
request.WithMessage(message);
request.WithSource(from);
if (emailReplyTo != null)
{
List<String> replyto
= emailReplyTo
.Replace(", ", ",")
.Split(',')
.ToList();
request.WithReplyToAddresses(replyto);
}
if (returnPath != null)
request.WithReturnPath(returnPath);
SendEmailResponse response = ses.SendEmail(request);
SendEmailResult result = response.SendEmailResult;
}
catch (Exception e)
{
}
}
}
}
I think that the request are rejected if we are trying to send more messages per second then the allowed limit.
I found this in the SES Blog http://sesblog.amazon.com/post/TxKR75VKOYDS60/How-to-handle-a-quot-Throttling-Maximum-sending-rate-exceeded-quot-error
When you call Amazon SES faster than your maximum allocated send rate, Amazon SES will reject your over the limit requests with a "Throttling – Maximum sending rate exceeded" error.
A "Throttling – Maximum sending rate exceeded" error is retriable. This error is different than other errors returned by Amazon SES, such as sending from an email address that is not verified or sending to an email address that is blacklisted. Those errors indicate that the request will not be accepted in its current form. A request rejected with a "Throttling" error can be retried at a later time and is likely to succeed.
If they would queue the requests this would be a great option but our experience is that they don't. Please let me know if I understand something wrong here.
I've since found out the answer is that they are rejected.
If you attempt to send an email after reaching your daily sending quota (the maximum amount of email you can send in a 24-hour period) or your maximum sending rate (the maximum number of messages you can send per second), Amazon SES drops the message and doesn't attempt to redeliver it.
https://docs.aws.amazon.com/ses/latest/DeveloperGuide/reach-sending-limits.html
I'm getting stuck on this situation and on the way finding the best way for resoling.