Allowed memory size of 134217728 bytes exhausted

Swift Mailer is a fantastic library for sending email with php. Discuss this library or ask any questions about it here.

Moderators: Chris Corbyn, General Moderators

Post Reply
gtraxx
Forum Newbie
Posts: 1
Joined: Sun Jan 16, 2011 4:49 pm

Allowed memory size of 134217728 bytes exhausted

Post by gtraxx »

Hello, I encounter a problem with sending a lot of newsletters with
email address.
I use the anti-flood plugin and Throttler plugin got an error message
about memory!
What can I do to solve this problem?

My error :
<br />

<b>Fatal error</b>: Allowed memory size of 134217728 bytes exhausted
(tried to allocate 1746643 bytes) in <b>/library/swiftmailer/classes/
Swift/Transport/MailTransport.php</b> on line <b>151</b><br />

Thanks :)
mpetrovich
Forum Commoner
Posts: 55
Joined: Fri Oct 19, 2007 2:02 am
Location: Vancouver, WA, USA

Re: Allowed memory size of 134217728 bytes exhausted

Post by mpetrovich »

There are a few things you might be doing to produce this error. 1) You could be creating a large array of the recipients which is exhausting the memory. 2) You could also have a text string or array that you are appending somewhere that is building upon sending each message.

If you are sending to a large list from a database, you will need to grab a record at a time, and send out the message when each record is read. Watch to make sure you are not growing any string variables or arrays, that you do not need to keep.
gnutix
Forum Newbie
Posts: 3
Joined: Fri May 28, 2010 5:23 am

How to send huge amount of emails without exceed PHP memory

Post by gnutix »

Hello gtraxx,

I was encountering the same problem with sendings of over 20'000 emails. Below is an extract of my code, that allowed me to send over 100'000 mails without crash.

1) I get all the contact's informations from the database in one single query, and at each row I save the information serialized in a file. This gives us something like :

Code: Select all

$filePath = 'the/path/for/my/File.txt';

// We get the information from the database
$res = mysql_query("SELECT DISTINCT email, other, fields... FROM contacts WHERE ...");

// We make a loop on the contacts
while (false !== ($contactInfo= mysql_fetch_assoc($res))) {
	
	// We put 'em in the file, each line containing the serialized datas of one contact
	file_put_contents($filePath, serialize(&$contactInfo)."\n", FILE_APPEND);
}
2) I make a loop on the file, until I get to the end and inside it, I select a range of contacts to do the sending :

Code: Select all

// Number of contacts to manage at a time
$rangeContacts = 1000;

// We create a pointer to the file in read mode
$fileHandler = fopen($filePath, 'r');

// We read the file until we get to the end
while (false === feof($fileHandler)) {
	
	// We loop on the range of contacts to manage
	for ($i = 0; $i <= $rangeContacts; $i++) {
		
		/**
		 * We get the array of datas of the contact and remove the "\n"
		 * 
		 * @internal The "fgets" function reads *only* the part of the file we ask, so there's no risks of
		 * PHP Fatal Error "Allowed memory exceeded" if $contactsRange is small enough.
		 */
		$contactInfo = unserialize(trim(fgets($fileHandler), '0x0A'));
		
		// We put the datas in an array for SwiftMailer
		if (is_array($contactInfo)) $swiftRecipients[] = $contactInfo['email'];
		
		// Optimisation
		$contactInfo = null;
	}
	
	// We add the emails in Swift and make the sending
	$message->setTo(&$swiftRecipients);
	$swiftMailer->batchSend($message);
}
		
// We remove the pointer, the variable and the file
fclose($fileHandler);
$fileHandler = null;
unlink($filePath);
And if you want some simple advice for optimisation:
  • Use references everywhere you can for arrays / objects (like in "$message->setTo(&$swiftRecipients);")
  • Set to null all the variables you don't need anymore in your script (like the "$fileHandler = null;" at the end), it will clear them from memory
  • Do only what you really need to do, and try to do them out of the loops
Hope it will help ya or others.
gnutix
Post Reply