Laravel Mail queue different than Mail send - php

I'm trying to send mails using simple DB queue driver. Queue works fine, but problem is with mail content. When I'm sending email with send() method all is fine. Content is like it should be, but when trying to use queue, content is not as should be, I get content from 2nd line of this code (but content is changed after second line before queueing mail):
$mail->textPlain = strip_tags($request->content);
$mail->textHtml = base64_encode($request->content);
$mail->date = date("Y-m-d H:i:s");
$mail->save();
//This mail content will be sent
$thread = $this->getThread($ticket, $request->content);
$mail->textPlain = strip_tags($thread);
$mail->textHtml = base64_encode($thread);
Email::to($ticket->from)->queue(new Reply($mail));
That part where I'm appending $mail object is not shown in final message when using queues, final message is - $mail->textHtml = base64_encode($request->content);.
But should be -
$thread = $this->getThread($ticket, $request->content);
$mail->textPlain = strip_tags($thread);
$mail->textHtml = base64_encode($thread);
$mail is object from Mail model.
Process: I'm storing in DB just last reply from input, but final reply message delivered to recipient is all messages in thread.
reply.blade.php
{!! base64_decode($reply->textHtml) !!}

When the job gets serialized, the Model instances aren't serialized as a representation of the current object. There is basically an identifier stored which is used to retrieve the Model instance from the database when the job is unserialized. (class type, id value to query for, loaded relationships, roughly)
Anything that isn't persisted wont be available when the model is retrieved from the database.
Illuminate\Queue\SerializesModels -> Illuminate\Queue\SerializesAndRestoresModelIdentifiers
If you need other information, you can have more variables passed to the Job when created.

Related

Sendgrid multiple emails with different contentType?

Im trying to send multiple emails with Sendgrid, and everything works fine, unless i change Content type meanwhile.
Is it possible to change contentType determined which email im sending to?
The error:
{"message":"If present, text/plain and text/html may only be provided once.","field":"content","help":null}]
Code:
foreach ($emailAddress as $key => $email) {
$addresses["$email"] = "$key";
$perzon = new Personalization();
$perzon->addTo(new To((trim($email))));
$mail->addPersonalization($perzon);
if ($email == "example#example.org" || $email == "iexample2#example2.org") {
$mail->addContent(
"text/plain",
str_replace(" ", "", $messagePlain)
);
$mail->setSubject($subject);
} else {
$mail->addContent(
"text/html",
nl2br($message)
);
$mail->setSubject($subject);
}
}
It looks like you're re-using the $mail object each time you loop. And addContent() adds extra content to the email (clue's in the name! :-)), it doesn't overwrite existing content. So by the time you're on the second email you could have added two lots of plaintext content (for example), and the mailing class can't cope with that because it doesn't know which version of the plaintext content you really want to send - an email cannot contain more than one version of the same kind of content (because if it did, again the receiving client wouldn't know which version to display either).
So wherever you are declaring the $mail object (it isn't shown in your question), you need to move that line inside your foreach loop and that should resolve the issue, because you'll have a fresh instance of the email object each time, instead of keep adding things to an existing one.
Also I'd expect you need to move the code which sends the email inside the loop too, otherwise it'll only send once (using whatever was the last settings generated by the loop).

Can a Queue be rescheduled in OctoberCMS

Task:
I am creating a way that a frontend user can send a message and schedule a time for it to be delivered. To accomplish this, I am storing the message info in database tables and then Setting a queue to fire a send function at the appropriate time.
Question:
If the user changes their mind about the time to send the message after this code is executed, is there a way to remove this from the queue and then re add it to fire at a different time?
Example
$data = ['message_id' => $this->messageModel->id];
$queue = Queue::later($this->send_at, 'KurtJensen\Twilio\Classes\SendQueue', $data);
// ==== Everything works great up to this point =======
// Don't know if this will work
// Can I get a queue identifier here?
$this->messageModel->queue_id = $queue->id;
$this->messageModel->save();
Then later to change time:
$this->messageModel= Message::find($id);
$q_id = $this->messageModel->queue_id;
// ==== I doubt this would work or if canceling a queue is possible =======
Queue::cancel($q_id);
$queue = Queue::later($new_time, 'KurtJensen\Twilio\Classes\SendQueue', $data);
$this->messageModel->queue_id = $queue->id;
$this->messageModel->save();

Multiple CC emails says email does not comply with RFC 2822, 3.6.2

I create a simple CC script that will attach from database to Mail::send. However, previous code was successfully submitting and working, until later this weekend, it went back to this message along with the Laravel error.
Swift_RfcComplianceException
Address in mailbox given [email1#domain.com,email2#domain.com]
does not comply with RFC 2822, 3.6.2.
This is the code where I pull out the email(s) from database. This will depend if all the properties have emails.
if( !empty($contact) ) {
$property_contact = implode(',', array_filter(array_unique($contact)));
}
// Output when using dd($property_contact);
// “email1#domain.com,email2#domain.com”
Here’s the script for Mail::send
//send email to owner
Mail::send('_dash.emails.profile', $contacts, function ($message) use ($property_contact) {
$ownerEmail = "myemail#info.com";
$ownerName = "Information";
$recipient_name = Request::get('firstname') .' '. Request::get('lastname');
$recipient_email = explode(';', Input::get('email')); // Need to explode the array if value are more than one
print_r($property_contact);
$message->from($recipient_email[0],$recipient_name);
$message->to($ownerEmail,$ownerName)->cc($property_contact);
$message->subject("Profile Update");
});
Explanation:
This is for the user when they updated their profile it will update/notify the admin about their new info along with the other property managers ($property_contact). These property managers will be added as CC and numbers of property managers will depend how many property this user connected.
If the user have 9 properties connection, whenever he update his profile, these 9 property managers will receive the update information.
Case Issue:
Base on Laravel error info, it does not comply the email format that passing from my script. I believe I do not understand the standard format that this Laravel is looking for from my script to pass the value. If I pass 1 value, it is working fine. But, whenever I add more emails, it ended up to this error.
Thank you for your help. I appreciate it.
cc() method accepts either one email or several email addresses in array.
So just edit Your $property_contact variable and You are good to go:
$property_contact = array_filter(array_unique($contact));
Code: https://github.com/laravel/framework/blob/5.2/src/Illuminate/Mail/Message.php#L132. Every method like to(), cc() bcc(), replyTo() using same method.

Can't use an array in Swift Mailer function

I'm using Swift Mailer to send emails to users. I've following script to send email to a number of users at a time.
$j=0;
while($row = mysql_fetch_assoc($email))
{
$message[$j]->addTo($row['email_invited']);
$mailer->send($message[$j]);
$j++;
}
I get the following error while doing this:
Fatal error: Cannot use object of type Swift_Message as array in
/home/public_html/example.com/people.php on line 21
If I try to send emails like this:
while($row = mysql_fetch_assoc($email))
{
$message->addTo($row['email_invited']);
}
$mailer->send($message);
It sends the email normally & every user gets it but the issue with that is every user can see what other users have got the email along with him. So basically in "To" field, every email is bound & thus every users gets to see all other email addresses.
What I want to achieve is every user should get a personalized email only even though it's sent in bulk. That is why I tried to use array & separate email but getting error in that.
Any idea how to achieve that?
How about doing. I think you need to create new instance of message (and maybe mailer too) in every loop.
while($row = mysql_fetch_assoc($email))
{
$mailer = Swift_Mailer::newInstance($transportName);
$message = Swift_Message::newInstance($subject);
$message->addTo($row['email_invited']);
$mailer->send($message);
}

Capture email smtp error with print_debugger without attachment dump

Scenario: I have a number of Codeigniter applications that I am improving the email delivery system to use a database queue. So my application logs all emails that need to be sent into the database. I run a cron job every minute to check this database queue and send out any pending emails (throttled to my server limits as needed).
It is all working fantastically and has dramatically improved our applications.
Part of the feature is it will record when emails are not sent, and will retry again later. As part of the process I update the database to include any error messages during the send attempts, for debugging later. I do this with $this->email->print_debugger().
Once again all working ok (normally).
The problem is if an attachment was included in the email, the attachment 'data' is dumped as part of the print_debugger() - so my database gets smashed with large text dumps of attachment data.
What I tried: So I went looking in the Email.php class of codeigniter, thinking I could extend the library to just not include the attachment data in the print_debugger() function - but it seems that the error that is returned from the function is actually from the SMTP server itself in another function. I cant see a way to stop the attachment data coming through on the error.
Question/Challenge: Can anyone see a way where I can capture an SMTP error, and the email headers - but not the attachment data? I'm happy to settle for not capturing any of the email body either (since I know what that is anyway in my database queue).
I believe that you can just extend the library. This is the current function:
public function print_debugger()
{
$msg = '';
if (count($this->_debug_msg) > 0)
{
foreach ($this->_debug_msg as $val)
{
$msg .= $val;
}
}
$msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".htmlspecialchars($this->_finalbody).'</pre>';
return $msg;
}
There are four main parts to what is returned:
_debug_msg - The debug messages
_header_str - The email's headers
_subject - The email's subject
_finalbody - The body of the message and the attachment data
Implementing a similar function, without _finalbody should give you the desired output but without the body and attachment data.
Here's an example solution, (with the class 'MY_Email' located here at: application/libraries/MY_Email.php):
class MY_Email extends CI_Email
{
public function my_print_debugger()
{
$msg = '';
if (count($this->_debug_msg) > 0)
{
foreach ($this->_debug_msg as $val)
{
$msg .= $val;
}
}
$msg .= "<pre>".$this->_header_str."\n".htmlspecialchars($this->_subject)."\n".'</pre>';
return $msg;
}
}
Looking through the code for the class, I think that $_body may contain the body data without the attachment data, so it could be worth trying to append $this->_body, rather than $this->_finalbody to the function. I've haven't tested this, so I'm not certain.
Hopefully this helps!

Categories