Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, Ed, biapar, Willr, Ingo, swaiba

[SOLVED kind of] Email corruption from inside loop


Go to End


3 Posts   1959 Views

Avatar
StuM

Community Member, 59 Posts

27 January 2009 at 9:43pm

Edited: 29/01/2009 8:56am

I've been pulling my hair out with this.

I have some code that sends bulk emails. They have customised messages to each recipient and generates the message on the fly.

Sometimes it can do 20, sometimes 50, but never reach 100 without the subject and plaintext version fields turning into the 'from' field. Running the same script under the same conditions will yield different results(i.e. send a different number of emails before stuffing up). The 'CC' field also gets set to the sender along the way I've just noticed as well.

I'm running a trunk version from September, I did a WinMerge between the email classes in the latest version and the trunk version, and they're the same. Upgrading not an option at this time, and probably won't help in this situation.

Any ideas at all

Avatar
StuM

Community Member, 59 Posts

28 January 2009 at 10:25am

Edited: 28/01/2009 10:47am

I've done more tests on another server which is running 2.3.0-rc2. Test code below:

for ($i = 0; $i < 100; $i++)
{
    $email = new Email();
    $email->to = 'mail@example.com';
    $email->from = 'mail2@example.com';
    $email->subject = 'This is a test';
    echo $email->debug();
}

No body is added in this case, but makes no difference anyway. This code will sometimes get through 10, one test got to 34, before the 'subject' and 'to' are changed to the 'from' address, and cc and bcc headers added with the from address.

* Instantiating email object outside of loop makes no difference
* Unsetting email object makes no difference
* adding a usleep appears(although still random) to allow you to send more emails before it stuffs up
* adding echo $email->to after send will also have the from address set
* once it stuffs up, all emails afterwards are stuffed - it's like it's setting a global switch to mess up all of the emails

I'd also like to note that instantiating the email object outside of the loop causes even weirder behaviour when there is content, such as the subject getting set as the html body, and cc and bcc headers getting added with the html body

This is nuts!!!

Avatar
StuM

Community Member, 59 Posts

29 January 2009 at 8:55am

Ok, I submitted this issue to the bug tracker and it was dismissed as a non-issue. I then updated my versions Email.php. Mailer.php and SS_Viewer.php to the latest trunk versions, and it still is an issue.

In the end, I created a basic class wrapper on Email, and replaced the processVariables function. There is a suspicious looking for loop in there that does alter all of the headers that are getting changed, so now I have:

class GFEmail extends Email
{
	
	/**
	 * Load all the template variables into the internal variables, including
	 * the template into body.  Called before send() or debugSend()
	 * $isPlain=true will cause the template to be ignored, otherwise the GenericEmail template will be used
	 * and it won't be plain email :) 
	 */
	protected function parseVariables($isPlain = false) {
		if(!$this->parseVariables_done) {
			$this->parseVariables_done = true;

			// Parse $ variables in the base parameters
			$data = $this->templateData();
			
			/* nuked this
			foreach(array('from','to','subject','body', 'plaintext_body', 'cc', 'bcc') as $param) {
				$template = SSViewer::fromString($this->$param);
				$this->$param = $template->process($data);
			}
			*/
			
			// Process a .SS template file
			$fullBody = $this->body;
			if($this->ss_template && !$isPlain) {
				// Requery data so that updated versions of To, From, Subject, etc are included
				$data = $this->templateData();
				
				$template = new SSViewer($this->ss_template);
				
				if($template->exists()) {
					$fullBody = $template->process($data);
				}
			}
			
			// Rewrite relative URLs
			$this->body = HTTP::absoluteURLs($fullBody);
		}
	}
}

and all seems to be working fine for my needs, hopefully this can help somebody else if they experience the same issue.