I am new to simplenews and trying to find the optimal setting to run it

my assumptions / questions

- simplenews depends on cron (at least for big lists)
- max_execution_time might stop a cron from delivering SOME emails, Am I right ?
- simplenews DOES NOT know which emails were not delivered (in order to send on the next cron run), Am I right ?

Tweak simplenews / cron / max execution time

changed timestamp in dblog.admin.inc > dblog_overview line 80
from

format_date($dblog->timestamp, 'small'),

to

	format_date($dblog->timestamp, 'custom', 'm/d/Y - H:i:s'),

this way I can see the seconds each email is going out and calculate
SBTx = time of Xth email out - time first email out
where
SBTx = time it roughly takes simplenews to send x number of emails (cron throttle set to x)

and this at all times SHOULD BE LESS than

print "max execution time = ". ini_get('max_execution_time');

THUS

If you server is not in "SAFE MODE" you can probably change/include

<IfModule mod_php4.c>
php_value max_execution_time      60
</IfModule>

in .htaccess but keep it under 300 (5 minutes) otherwise you might get in trouble with your web host
abusing your web resource usage (if you are on a shared server)

I can adjust the simplenews throttle such that
cron throttle < (max_execution_time * x ) / SBTx

and lastly set cron interval > max_execution_time

My feature request for simplenews

a way for simplenews to present us with all the information above
ideally with a message in the system logs similar to this:
Simplenews sent 100 emails in 5 seconds. User's max execution time = 90 seconds
this way one can make "educated" adjustments to throttle, cron interval, max_execution parameters

which can easily be achieved with this code


$dat = getrusage();
$utime_before = $dat["ru_utime.tv_sec"];

/*
 * This is the place where the code to be TIMED should go
 */

$dat = getrusage();
$utime_after = $dat["ru_utime.tv_sec"];

$utime_elapsed = ($utime_after - $utime_before);

echo "Simplenews sent x emails in $utime_elapsed seconds.  User's max execution time = ". ini_get('max_execution_time');

if something does not make sense please correct me

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

spade’s picture

I second this and like to ask if this can be implemented in 5.x as well? Please.

Kind regards,

Frank

pixelpreview@gmail.com’s picture

yes I have alaways the same problem , some people receive the same email 2 or 3 times
I will try these solution for drupal 5

Sutharsan’s picture

@GiorgosK, please provide a patch for a watchdog message as you described. This is a good simplenews core functionality.

Sutharsan’s picture

Status: Active » Fixed
FileSize
2.75 KB

I made the attached patch for this functionality. The elapsed time is reported in the Log, the available time is added to the description of the cron throttle setting. GiorgosK thanks for the idea.

Attached patch is committed.

GiorgosK’s picture

You are welcome Sutharsan,
if I was good with patches and knew this module enough I would have created this patch myself.

Thanks for taking the time to create it.

I tried the last development snapshot (which includes these changes) and they look indeed very good

I would definitely add the max execution time in the watchdog message ONCE again

This
4 emails sent successfully in 0.6 seconds.
I would make
4 emails sent successfully in 0.6 seconds (< max exec. time = 30 Sec)

to relate the two values in such a way to make the user understand that MAX EXECUTION TIME should not be exceeded.

NOTE: There is a spelling error in your patch "max exection time"

Sutharsan’s picture

Status: Fixed » Needs work

I do not want to add (semi) static information to a watchdog message. If it is always the same, it will be ignored. The Send email settings is the place where the admin sets the cron throttle and needs to know the max time.

Perhaps the user should be warned if sending time take more than 80% of the max execution time. But this percentage is arbitrarily. Do you have any experience with a save margin (as percentage or seconds)?

Alternatively sending should be stopped if 80% of the max execution time is spend. However this will cause a problems with sending newsletters without cron because not all emails are send, and there may be no cron to send the remaining. But on the other hand exceeding the max time will cause problems any way.

GiorgosK’s picture

Ideally you would want simplenews to be adjusting the Cron Throttle on its own and in theory its not hard to do!!

Here is what I was thinking

After every email is send calculate the TOTAL TIME TAKEN (TTT) for the whole batch and compare it to the MAX EXECUTION TIME

If the TTT > 80% of MAX EXECUTION TIME then
- stop the CURRENT BATCH SENDING
- set Cron throttle to an appropriate value with a warning message ( Cron throttle value was adjusted to make sure all emails were sent)

Lets say 100 emails send in 8 seconds with MAX EXECUTION TIME 10 secs
Adjust the Cron Throttle to 100 and send a warning ...

If that can be implemented an email will never be lost again ...

Hope it makes sense

Sutharsan’s picture

You are right but
1. there are more reasons to limit the number per cron job. Like a max number of emails per hour set by a hoster and other cron jobs that also need time.
2. this is theory ...
After a few hours investigation I found out that the PHP max execution time is approximately the sum of user time and system time as you can get with getrusage(). It does not correlate with time() because "Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running." (see: set_time_limit()). So getrusage() is the way to go. But getrusage() is not available on windows platforms, so we need a fallback.

time() is not suitable to measure the execution time at all. Sending 1500 emails from my test site takes 35 seconds (time()) and 2.1 seconds PHP execution time.

Many scripts prevent the max execution time problem by increasing the max execution time limit or disabling it using set_time_limit(). But there is no real need to do this here. We send discrete emails and can break any point we want, unlike of example uploading a large file. And further safe mode prevents changing the time lime.

A fall back is also required for the situation where cron is not used, but emails are send immediately.

Sutharsan’s picture

Status: Needs work » Needs review
FileSize
4.85 KB

Attached patch does what I described.

Sutharsan’s picture

Status: Needs review » Fixed

Patch committed.
Note that this functionality does NOT work on windows platforms. I expect that the elapsed time in the log will be 0.0 seconds. Feedback from users with drupal on a Windows platform is highly appreciated.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for two weeks with no activity.

GiorgosK’s picture

Status: Active » Closed (fixed)

Sutharsan,
thanks for fixing this, I have not tested it though

on a second thought I have read that many SHARED HOSTS
are requiring from their clients to send emails with a delay between
each email for a SET NUMBER OF SECONDS
(email, pause for x seconds, email, pause for x seconds etc)

Does simplenews wait/pause between emails ?
Is it easy to have this kind of control where one
can specify the amount of seconds to wait
between emails ?

This will allow for a fine tuning of email delivery
(as the title of this issue is) and will prevent
greatly the failure of sending emails

I am pretty sure that the time a process is waiting (sleeping)
does not count against the MAX EXECUTION TIME
(ONLY THE ACTUAL EXECUTION TIME)
thus sleeping between emails can work to simplenews benefit ...

On a different note: allowing a few seconds between emails
will greatly reduce the chance of a person being labeled as
spammer ...

GiorgosK’s picture

Status: Closed (fixed) » Active

I activated the request, but feel free to close it
if you think its too much trouble ...

Sutharsan’s picture

Status: Closed (fixed) » Fixed

This is a different subject, the initial request was about max execution time.
All my sites and my customer's run on shared hosts. I have only encountered one host who restricted to max 20 smtp connections at once, this forced me to send in batches of < 20. I remember one similar issue in the queue. Are you talking assumptions or actual problems? Please open a new issue, if this proposal fixes actual problems.

GiorgosK’s picture

Not talking hypothetical situations here but REAL situations
and the hosts that ABSOLUTELY need 1 email every 6 seconds are quite a lot

The following list I found within two minute of searching on google.com

http://www.binaryvibes.co.in/shared-hosting-e-mail-policy
http://www.firstpro.co.uk/policies/email-policy
http://www.webintuitions.com/tos.php
http://www.nocohosting.com/tos.html
http://www.gressing.com/emailsending.htm
http://www.henchmenproductions.com/web-hosting/mailing-policy/
http://en.ahibo.net/mailpolicy.html
http://www.tmzhosting.com/mailpolicy.php
http://www.vesnasolutions.com/termsofservice.html
http://owntruth.com/owntruth_tos.html
http://www.jestient.com/termshost.htm

or search for more
http://www.google.com/search?q="1+email+every+6+seconds"

its not my PERSONAL problem but I am saying its a problem
that DOES exist and I don't think its that difficult to implement

create another setting for "SLEEP BETWEEN EMAILS"
and set it to 0 by default to be compatible with what you
have in place right now

if you want this on a different issue I will be happy to do it but
I consider it "TWEAKING SIMPLENEWS THROTTLE"

GiorgosK’s picture

Status: Fixed » Active

Such setting does exist with other newsletter packages
for example phplist uses

# Pause between messages (in seconds) to avoid overloading the server:
define('MAILQUEUE_THROTTLE',1);

there is a nice discussion on the documentation about it
http://docs.phplist.com/PhpListConfigSendRate

Sutharsan’s picture

Sending a mailing on a one-email-per-6-seconds host is like filling a bath tub with a thee cup. My advice: get another host.
Still, I can see a need for this, but I'm not sure if simplenews is the right place. It is not just simplenews who suffers from this problem, all mass mailing applications do. Perhaps a downstream is a better place.

Implementing this in simpelnews may not be too difficult. The biggest problem I see is how to create a trigger that fires every x seconds fully in the background. If you use a function with sleep() or usleep() and you call it with poormanscron, the user will see a white screen. This should not happen.

If you can build a prove of concept, I would be interested for simplenews integration.

Sutharsan’s picture

Since PHP has no multi threading, perhaps this can be done in the manner of cron.php. A php file called by a separate crontab process. For example every hour crontab calls example.com/sites/all/modules/simpelnews/mail_cron.php. This starts a process which runs for a bit less than one hour. The process calls simplenews_mail_spool() every x seconds to send y emails. It just has to make sure that simplenews_cron() or any other calls to simplenews_mail_spool() are inhibited. This process should monitor is't own PHP max execution time.
This can only be used in combination with crontab (or other external cron triggers) and not with poormanscron.

GiorgosK’s picture

about #17
Sorry Sutharsan

I thought you could just call sleep($waitbetweenemails) and you are done

Are you saying that this implementation would only be good for crontab > cron.php but not for poormanscron usage right ??

I don't know the inner workings of drupal (let alone poormanscron)
I could not have guessed ...

Sutharsan’s picture

Sleep() is the trick but it has important side effects. No poormanscron is one.
Perhaps this is the time to start looking at the Drupal engine after driving it for so many years ;)

Sutharsan’s picture

I like to see a feature in simplenews that can send emails in with frequent small batches like phpList does, using the same three parameters: batch size, time between batches, max duration. This should be a cron driven but separate from drupal's cron. i.e. mail_cron.php instead of cron.php. Who wants to develop this feature?

Sutharsan’s picture

Title: Tweaking simplenews throttle - cron - max execution time » Improve simplenews throttle
Version: 6.x-1.x-dev » 7.x-1.x-dev
FileSize
29.1 KB

Attached is the first version to improve the simplenews throttling system. This patch is based on ideas of phplist referred in #16 and the observation that simplenews cron should not be run with poormanscron.

Instructions:
- patch simplenews HEAD with the attached
- Move/copy the mail_cron.php file to your web root
- Setup cron(tab) to call mail_cron.php
- Setup simplenews mail settings as admin/settings/simplenews/mail
- Set 'Cron mail limit' to the limit set by your host. e.g. 600 emails per day
- Set 'Mail cron duration' equal to the duration set for cron(tab). e.g. 1 hour
- Set 'Mail method':
In the above example Batch sends 25 emails (= 600/24) and wait for 1 hour (= cron duration).
Throttle sends single emails with 2.4 seconds (average) in between the mails, resulting in 25 emails (= 600/24) in one hour (= cron duration).

If your system sends other emails apart from simplenews, you should reduce the cron mail limit. For example to 580 emails, which leaves space for other applications to send 20 emails per hours.

Sutharsan’s picture

Status: Active » Needs review
mcjudd’s picture

Hi there

Great module, but I am quite a newbie when applying patches.

So my questions are:

- how do I apply this patch and
- where (which folders) should I copy this patch too?

I have set up my contributed modules structure in sites/all/modules/contributions/

Is there anything else I would need to do to get this up and running (ie. run update.php?) Would I expect to see any new options etc in the Simplenew tab etc?

Thanks for your help

Sutharsan’s picture

To apply a patch see: http://drupal.org/apply/patch

Sutharsan’s picture

FileSize
30.12 KB

New patch attached.
Changes:
- Old cron sending method no longer triggered by cron.php.
- Status results changed in simplenews_mail_spool().
- Documentation changes in simplenews_mail_spool().

mcjudd’s picture

Status: Needs review » Closed (fixed)
mariano.barcia’s picture

Hi,

I don't see this committed anywhere in the CVS messages. Checked the source code, and it's not there... why was it closed?

I'm needing this feature since Hostgator requires the sending in batchs of no more than 500 emails per hour each batch, throttled down to 1 email per 8 seconds.

Should I apply this patch and review/test? Thanks.

Sutharsan’s picture

Status: Closed (fixed) » Needs review

yes, please apply to HEAD and report you results.

mariano.barcia’s picture

Thanks. Ok, we've applied the patch against the Oct 25 dev version available for download in the module page.

3 hunks failed, and had to be applied manually. One minor issue when doing so with the simplenews.module file:
There are 2 lines that doesn't appear to be modified, but are not in the -dev version nor in added the patch. After this

// Update results for reporting in newsletter admin panel.
simplenews_send_status_update();

comes

variable_set('simplenews_last_cron', time());
variable_set('simplenews_last_sent', count($mail_sent));

but the variable_set() calls were not marked as "added" in the patch. I just added them, hoping it will be fine. Please confirm this is how it's supposed to be.

    // Update results for reporting in newsletter admin panel.
    simplenews_send_status_update();
    variable_set('simplenews_last_cron', time());
    variable_set('simplenews_last_sent', count($mail_sent));

We'll be testing and reporting the results soon.

mariano.barcia’s picture

After cleaning the theme registry, we got the screen attached at admin/settings/simplenews/mail

Usually, cron.php (not poormanscron) will run every hour. We DON'T have to setup a scheduled call to mail_cron.php do we?

A more general example:
Suppose we have a list of 1200 subscribers. We have cron.php firing each hour. The shared host imposes these restrictions:
- Blasts should happen overnight
- no more than 500 emails per hour
- throttled (1 email each 8 seconds approx.)

We want to use simplenews, how would we configure it?

Thanks in advance.

mariano.barcia’s picture

Well, with cron.php running every hour, emails are not being sent...I could use a little bit of help here...TIA!

rsevero’s picture

I'm interested in trying the patch from #26 but as per #30 it's not applying cleanly. Is there a new version of the patch so I can test it?

miro_dietiker’s picture

ikeigenwijs’s picture

subscribe

Simon Georges’s picture

As we're close to an agreement on #361071: Use locking to eliminate duplicate emails from concurrent simplenews cron runs., I'm proposing to close this one as "duplicate", waiting for the completion of the other issue in 6.x-2.x before porting it to 7.x.

@miro_dietiker, @Sutharsan, any opposing thought ?

miro_dietiker’s picture

Status: Needs review » Closed (works as designed)

Well, throttling is not realls the same as the concurrency issue.
But still Closing.

We have implemented elysia_cron to allow you fine-grained controle over cron tasks.
If you need further controle over the time simplenews sends, add custom rules to elysia_cron.
#1010684: Support Elysia Cron hook_cronapi

If we need some further tweaking in the throttle algorighm, please reopen.

I could even recommend you to use drush to call the simplenews cron separately and disable it on the regular cron run. You'll have perfect controle over it that way.

Drupal itself should improve its cron / background task halding... instead of every module again...

j1ndustry’s picture

Has anyone successfully implemented Simplenews throttling to comply with email restrictions common to cheap shared hosting (example #31)? After reading through this thread, it does not seem like there have been clear successes. I'd love hear some strategies that worked.

I've used PHPList in the past, but I'd love to be able to integrate newsletters more closely with drupal data.