Page 1 of 1

problem with FileEmbedder

Posted: Fri Dec 07, 2007 1:14 pm
by zapalka
Elo.

First : great script

... but i have a problem with FileEmbedder

i am sending 30 mails per package... and time to time i have this error and scripts stops ;(
Fatal error: Uncaught exception 'Swift_Message_MimeException' with message 'Something went wrong whilst trying to move some MIME parts during an attach(). The MIME component threw an exception:<br />Cannot remove child part identified by '4759929241902' as it does not exist. Consider using hasChild() to check.' in /xxx/lib/Swift/Message.php:542
Stack trace:
#0 /xxx/lib/Swift/Plugin/FileEmbedder.php(349): Swift_Message->attach(Object(Swift_Message_EmbeddedFile))
#1 [internal function]: Swift_Plugin_FileEmbedder->embedRemoteFile(Array)
#2 /xxx/lib/Swift/Plugin/FileEmbedder.php(418): preg_replace_callback('~? (<(?:img)...', Array, '<!DOCTYPE HTML ...')
#3 /xxx/lib/Swift.php(171): Swift_Plugin_FileEmbedder->beforeSendPerformed(Object(Swift_Events_SendEvent))
#4 /xxx. in /xxx/lib/Swift/Message.php on line 542
:cry: :cry:

ANY IDEA ?

sometimes 2 mails, sometimes 15 mails, sometimes 30 mails go without problem, and somtimes i get this error ;(

Posted: Tue Dec 11, 2007 9:12 pm
by Chris Corbyn
Code please :)

Re: problem with FileEmbedder

Posted: Thu Jan 24, 2008 4:20 pm
by Kieran Huggins
I'll revive this thread since I had the same problem 3 times during 600 messages, batch size of 20

code:

Code: Select all

class Mailer{
/* 
// these seem to mess up the forum code highlighter, but they are uncommented
 
    const FROM_NAME = 'From Name';
    const FROM_ADDR = 'from@domain.com';
    const DB_HOST = 'localhost';
    const DB_USER = 'LUSER;
    const DB_PASS = 'SECRET';
    const DB_NAME = 'mailer';
    const CHECK_INTERVAL = 1;
    const MAILER_TYPE = MAILER;
    const SMTP_HOST = 'localhost';
    const SMTP_USER = 'LUSER';
    const SMTP_PASS = 'SECRET';
    const MAX_BATCH_SIZE = 20;
    const FILE_PATH = 'attachments';
*/  
    private static $db = null;
    private static $smtp = null;
    private static $swift = null;
 
    public function __construct(){
        require(dirname(__FILE__).'/Swift/lib/Swift.php');
        require(dirname(__FILE__).'/Swift/lib/Swift/Connection/SMTP.php');
        require(dirname(__FILE__).'/Swift/lib/Swift/Authenticator/LOGIN.php');
        require(dirname(__FILE__).'/Swift/lib/Swift/Iterator/MySQLResult.php');
 
        self::$db = MySQL_pconnect(self::DB_HOST, self::DB_USER, self::DB_PASS) or die(MySQL_error());
        MySQL_select_db(self::DB_NAME,self::$db) or die(MySQL_error());
 
        self::$smtp =&new Swift_Connection_SMTP(self::SMTP_HOST);
 
        self::$swift =&new Swift(self::$smtp);
    }
 
    public function sendQueue($message_id){
        $queue = MySQL_query("SELECT * FROM `queue` WHERE `sent` IS NULL AND `message_id`='$message_id' ORDER BY `id` ASC LIMIT ".self::MAX_BATCH_SIZE) or die(MySQL_error());
 
        // are we done?
        if(MySQL_num_rows($queue)==0) return false;
 
        // set up recipientList
        $recipients =& new Swift_RecipientList();
 
        // fill recipient List
        $sent = array();
        while($row = MySQL_fetch_assoc($queue)){
            $recipients->addTo(new Swift_Address($row['address'],$row['name']));
            $sent[] = $row;
        }
 
        $from = new Swift_Address(self::FROM_ADDR,self::FROM_NAME);
                
        $msg = MySQL_query("SELECT * FROM `messages` WHERE `id`='$message_id' LIMIT 1") or die(MySQL_error());
        $msg = MySQL_fetch_assoc($msg);
 
        $message =& new Swift_Message($msg['subject']);
        $message->attach(new Swift_Message_Part($msg['text']));
        // html?
        if(!is_null($msg['html'])) $message->attach(new Swift_Message_Part($msg['html'], "text/html"));
 
        // attachments?
        $attachments = MySQL_query("SELECT * FROM `attachments` WHERE `message_id`='$message_id'") or die(MySQL_error());
        while($row = MySQL_fetch_assoc($attachments)){
            $message->attach(new Swift_Message_Attachment(file_get_contents(self::FILE_PATH.'/'.$row['md5']), $row['filename'], $row['mimetype']));
        }
 
        $batch =& new Swift_BatchMailer(self::$swift);
        $batch->send($message, $recipients, $from);
 
        // mark the queue as sent (I should be doing error checking here)
        MySQL_query("UPDATE `queue` SET `sent`=NOW() WHERE `message_id`='$message_id' AND `sent` IS NULL ORDER BY `id` ASC LIMIT ".self::MAX_BATCH_SIZE) or die(MySQL_error());
 
        return $sent;
    }
 
    public function createMessage($subject,$text,$html=null){
        if(is_null($html)){
            $msg = MySQL_query("INSERT INTO `messages` (`subject`,`text`) VALUES ('$subject','$text')") or die(MySQL_error());
        }else{
            $msg = MySQL_query("INSERT INTO `messages` (`subject`,`text`,`html`) VALUES ('$subject','$text','$html')") or die(MySQL_error());
        }
        return MySQL_insert_id(self::$db);
    }
 
    public function createAttachment($message_id,$file){
        $md5 = md5(file_get_contents($file['tmp_name']));
        $mimetype = mysql_real_escape_string($file['type']);
        $filename = mysql_real_escape_string($file['name']);
        if(!move_uploaded_file($file['tmp_name'],self::FILE_PATH.'/'.$md5)){
            die('error storing file');
        }
        $msg = MySQL_query("INSERT INTO `attachments` (`message_id`,`filename`,`md5`,`mimetype`) VALUES ('$message_id','$filename','$md5','$mimetype')") or die(MySQL_error());
        return MySQL_insert_id(self::$db);
    }
 
    public function add_to_queue($message_id,$address,$name=null){
        if(is_null($name)){
            $msg = MySQL_query("INSERT INTO `queue` (`message_id`,`address`) VALUES ('$message_id','$address')") or die(MySQL_error());
        }else{
            $name = MySQL_real_escape_string($name);
            $msg = MySQL_query("INSERT INTO `queue` (`message_id`,`address`,`name`) VALUES ('$message_id','$address','$name')") or die(MySQL_error());
        }
        return MySQL_insert_id(self::$db);
    }
 
    public function queue_all($message_id){
        $result = MySQL_query("SELECT * FROM `addresses` WHERE `active`=1");
        while($row = MySQL_fetch_assoc($result)){
            self::add_to_queue($message_id,$row['address'],$row['name']);
        }
    }
}
 
the sending code (a simple, in-house mailer, not public facing):

Code: Select all

if($_SERVER['REQUEST_METHOD']=='POST'){
    $m = new Mailer;
 
    $subject = !empty($_POST['subject'])?$_POST['subject']:'(no subject)';
    $text = !empty($_POST['text'])?$_POST['text']:'(no message)';
    $html = !empty($_POST['html'])?$_POST['html']:null;
 
    $msg = $m->createMessage($subject,$text,$html);
 
    // send to all in address book
    $m->queue_all($msg);
 
    foreach($_FILES as $file){
        $m->createAttachment($msg,$file);
    }
 
    #$m->sendQueue($msg);
    header("location:?send=$msg");
}
Error msg:
Fatal error: Uncaught exception 'Swift_Message_MimeException' with message 'Something went wrong whilst trying to move some MIME parts during an attach(). The MIME component threw an exception:<br />Cannot remove child part identified by '4799085945809' as it does not exist. Consider using hasChild() to check.' in /var/www/newsweek_sender/Swift/lib/Swift/Message.php:542 Stack trace: #0 /var/www/newsweek_sender/index.php(116): Swift_Message->attach(Object(Swift_Message_Attachment)) #1 /var/www/newsweek_sender/index.php(204): Mailer->sendQueue('10') #2 {main} thrown in /var/www/newsweek_sender/Swift/lib/Swift/Message.php on line 542

Re: problem with FileEmbedder

Posted: Mon Apr 14, 2008 7:59 pm
by frankgfy
i get a similar intermittent problem. but i am only sending one email at a time. just about 1 of of every 100 will fail with this thrown error -

"There was an unexpected problem building the email:Something went wrong whilst trying to move some MIME parts during an attach(). The MIME component threw an exception:<br />Cannot remove child part identified by '4803800513168' as it does not exist. Consider using hasChild() to check."

funny, if if the calling script catches this error and then tries to immediately reprocess the email with all the same code and options/files, it will go through ok (most of the time).

using -
Swift Mailer Version 3.3.2 for PHP5.

essential code:
$message = new Swift_Message($mailArgs['s']); //create the message (and subject)
$swift = new Swift(new Swift_Connection_SMTP($hostname, $portnum),php_uname("n")); //default to standard smtp port
$message->attach(new Swift_Message_Image(new Swift_File($embedInfoArray[0]), $embedname, $embedtype, $embedcid, "base64"));
$plainText = new Swift_Message_Part(new Swift_File($mailArgs['p']));
$message->attach($plainText);
$file = new Swift_File($mailArgs['m']);
$htmlPart = new Swift_Message_Part(new Swift_File($mailArgs['m']), "text/html");
$message->attach($htmlPart, "text/html");
$recipients = new Swift_RecipientList();
$recipients->addTo($TO); //"to@someperson.com"
$message->attach(new Swift_Message_Attachment(new Swift_File($attachInfoArray[0]), $attachname, $attachtype, "base64"));
$swift->send($message, $recipients, $sender)

Re: problem with FileEmbedder

Posted: Mon Apr 14, 2008 11:11 pm
by Chris Corbyn
Still not sure what caused this but hoping the next version of the plugin will see the end of it. I hate those pesky little bugs which just happen randomly.

Re: problem with FileEmbedder

Posted: Tue Apr 15, 2008 5:44 am
by frankgfy
while i cannot reproduce it reliably, it does happen to me about 20-30 times a day. is there anything i can put in the code to trap what might be happening and feed back to you for your debugging?

Re: problem with FileEmbedder

Posted: Tue Apr 15, 2008 6:12 am
by Chris Corbyn
I actually don't think the bug lies in the plugin. It certainly lies in Swift Mailer itself, but that plugin shouldn't be able to cause such an error. The bug is somewhere in the deep guts of the Swift_Message class. The attach()/detach() logic in that class is not the nicest bit of code in Swift I have to admit. Version 4 does it much simpler. It just re-attaches a modified list of children rather than doing what v3 is doing and trying accommodate a child into an existing list. Ugh :(