soonick / poMMo

poMMo
115 stars 51 forks source link

setRelay Question #179

Open hendiwsl opened 10 years ago

hendiwsl commented 10 years ago

Hi

I have set up all 4 smtp relays but however only the [smtp_1] is being used so I am getting a quota exceed.

Can anyone assist me I am aware of the setRelay element but cannot see how or where it is to be used

soonick commented 10 years ago

I took a quick look at the code and it seems like setRelay is not being called, it was probably never fully implemented.

hendiwsl commented 10 years ago

Thanks Soonick,

So you can only use smtp_1/a single smtp relay.

Is it quite a difficult element to implement considering that it is there on the user end as though it is a working feature

soonick commented 10 years ago

I agree, I think it won't be trivial to implement.

I am also not sure what the correct behavior should be. It could mean that it will balance the load by alternating smtp relays for each email or it could also mean that it will use the smtp1 unless it fails and then it will fallback to the next one.

hendiwsl commented 10 years ago

I'm far from an expert but I was thinking that the ideal behaviour would be something along the lines that all 4 smtp channels would fire off at the same time when a mailing starts/resumes (e.g. if the smtp_2, _3, _4 have values stored in it other wise if empty nothing happens for those channels)

Each subscriber is allocated a single smtp value from 1 ~ 4 (if active)

Example: My web host has a 100 email send limit per smtp username so using all 4 relays could increase my hourly send capacity to 400 per hour

1 hour / 100 mails = 36 seconds per mail (so I would set a single smtp relay batch period to 144 seconds to send an email to 4 subscribers every time the batch script runs )

Using all 4 smtp relays would mean 1 hour / 400 mails = 36 seconds per 4 mails (so I would set total load for smtp relay batch period to 144 seconds to send an email to 16 subscribers every time the batch script runs )

Option 1: Balanced sending across all relays splitting the queue on demand Where various smtp relay values have been inserted by admin the load would be balanced across all smtp relay channels. It would use the general throttle values to determine the balance of the send by allocating an smtp channel number to the subscriber on demand when the batch is called to send from the db mailing_queue

Throttling the mail settings across ALL the active relays: batch send period = 144 seconds (batch runs 25 times per hour) mail throttle per batch send period = 16

When mailing_queue script runs it will

check db for the smtp relays with values set (e.g. 1 ~ 4) if smtp has a value set as active
check for all subscribers which are unsent in the current mailing with the value '0' check or clear any smtp values to say '0' select the number of subscribers (mails) to send based on 'batch' value (e.g. 16) set the smtp value for each subscriber by asc loop allocation from active smtp relays 1 ~ 4 (depending on number of relays set as active) run script for batch send period

Option 2: Allocating each subscriber the designated smtp relay channel on initial mailing_queue submission with the throttle set per individual relay: -

Throttling the mail settings PER relay: batch send period = 144 seconds (batch runs 25 times per hour) ~default is 80 seconds throttle number of mails per relay, per batch send period = 4 mails per relay

Each subscriber selected for the mailing is allocated an smtp value on submit to db mailing queue through looping the active relays e.g. subscriber no#10510 = smtp_1 subscriber no#10517 = smtp_2 subscriber no#10518 = smtp_3 subscriber no#10519 = smtp_4

When mailing_queue script runs it will

add subscribers to db mailing_queue get active smtp relays 1 ~ 4 set the smtp value for each subscriber by asc loop allocation from active smtp relays 1 ~ 4 check for all subscribers which are unsent in the current mailing with the value '0' check smtp values not '0' (already allocated 1 ~ 4) select the number of subscribers (mails) to send based on 'batch' value (e.g. 16) run script for batch send period

soonick commented 10 years ago

Hey @hendiwsl,

Your idea sounds fine. I like Option 1 more because I don't like the idea of having a subscriber bound to a specific relay. If you are a developer and you want to start with the implementation I will be happy to help you with the details.

Regards, Adrian

hendiwsl commented 10 years ago

Hi

I'm not a developer or an expert - I'm just someone that could really do with having the solution implemented. I'm happy to discuss paying someone to finish off the functionality

soonick commented 10 years ago

Hello @hendiwsl,

If you find a developer you can hire to implement this functionality I will be happy to help him whenever he gets stuck.

Regards, Adrian

bch80 commented 10 years ago

Hello,

I'd be interested in that feature as well and kind of OK with PHP - though a bit rusty. Just went through mailngs_send4.php and found: $mailer->setRelay(unserialize($config['smtp_1'])); a quick and dirty first approach would be to simply use a random number instead of smtp_1 (which isn't real balance but it would distribute the load a bit better).

One question: Is there only one mailer object instantiated for one mailing or one for each mail? Adrian: How to get in touch with you to get a quick introduction? I'd donate some code.

Regards, Chris

soonick commented 10 years ago

Hello Chris,

I don't know the whole codebase, but we could have a chat and talk through possible solutions. In what timezone are you?

bch80 commented 10 years ago

I'm in China - GMT+8

bch80 commented 9 years ago

I'm still interested in this - so I restarted to drill the process down. This function sends everything out: function bmSendmail(&$to, $subscriber = FALSE) so it's possible to override smtp settings quick and super dirty like: $mailnr = mt_rand(1, 3); $config = PommoApi::configGet('smtp'.$mailnr); $smtp = unserialize($config['smtp_'.$mailnr]); and that worked as well (all data is correct after overriding some more vars) but the issue as it seems it the keep alive connection with the SMTP. It's just connected to smtp_1 all the time, and then again of course I can't use smtp_2 data ... Unfortunately I couldn't figure out yet where to initialise a new connection before sending - any idea?

altshiftzero commented 9 years ago

Hi Chris8080,

The function Stop in pommo_mta.php uses $this->_mailer->SmtpClose(); to close the smtp connection. You could add this in the same script in function processQueue() as following on line 350 - 353

 if (!$this->_mailer->bmSendmail($mail[0], $personal)) // sending failed, write to log
  $this->_failed[] = $mail[0];
  $this->_mailer->SmtpClose();
else
  $this->_sent[] = $mail[0];
  $this->_mailer->SmtpClose();

Or you can choose to put this in the bmSendmail() function after the sending has been completed. I did not test this, so you should try this in a development environment first.

bch80 commented 9 years ago

Hmm .. yes - that's an idea. I first tried to change PHPMailer to close the connection after sending mails out.

Now I changed it to your suggestion - but there seems to be an underlying mistake. I receive: Sending failed: SMTP Error: Could not connect to SMTP host. Started Mailing #19 quite frequently.

Seems like I'm just stumbling around in the code and I found several comments which hinted to migrate to another mailer lib which would solve this issue .. I'm currently setting up 5 pommos with 5 different accounts and split up my mailing list. Not nice but it seems as if I'm getting nowhere with a search for a software like pommo that can handle multiple relays. :(

altshiftzero commented 9 years ago

If you used the code as I gave previously it could be the problem that there is no { } for the if-statement while the code within the if is multi-lined. That is my mistake. This:

 if (!$this->_mailer->bmSendmail($mail[0], $personal)) // sending failed, write to log
  $this->_failed[] = $mail[0];
  $this->_mailer->SmtpClose();
else
  $this->_sent[] = $mail[0];
  $this->_mailer->SmtpClose();

Should be this:

 if (!$this->_mailer->bmSendmail($mail[0], $personal)){ // sending failed, write to log
  $this->_failed[] = $mail[0];
  $this->_mailer->SmtpClose();
} else { 
  $this->_sent[] = $mail[0];
  $this->_mailer->SmtpClose();
}

See if that helps.

bch80 commented 9 years ago

Thanks for your concerns. :) I added the {} - but the error is the same as if I'd hack PHPMailer to disconnect after sending. The PHP is right but the call stack might be not as I imagine and then Pommo can't connect to the next SMTP. :-S

Am 20.10.2014 um 18:04 schrieb Dempsey van Wissen:

If you used the code as I gave previously it could be the problem that there is no { } for the if-statement while the code within the if is multi-lined. That is my mistake. This:

if (!$this->_mailer->bmSendmail($mail[0], $personal)) // sending failed, write to log $this->_failed[] = $mail[0]; $this->_mailer->SmtpClose(); else $this->_sent[] = $mail[0]; $this->_mailer->SmtpClose();

Should be this: if (!$this->_mailer->bmSendmail($mail[0], $personal)){ // sending failed, write to log $this->_failed[] = $mail[0]; $this->_mailer->SmtpClose(); } else { $this->_sent[] = $mail[0]; $this->_mailer->SmtpClose(); }

See if that helps.

— Reply to this email directly or view it on GitHub https://github.com/soonick/poMMo/issues/179#issuecomment-59718263.

altshiftzero commented 9 years ago

Does it send the first e-mail? If so, it probably disconnects the server but does not connect to the second server. I'll try to look into it.