sending html and inline images using php Mail/mime - php

I am using php/Mail_mime to send styled html content using the code below.
$headers = array ('From' => $sender,
'To' => implode(',',$to),
'Subject' => $subject,
'Reply-To'=>'myemail#mydomain.com',
'MIME-Version'=>'1.0',
'Content-Type'=>'text/html'
);
/*end header*/
$this->mime = new Mail_mime();
$tt=$this->mime;
$tt->addBcc(implode(',',$bcc));
$tt->addCc(implode(',',$cc));
$tt->setTXTBody($text);
$tt->setHTMLBody($body);
$tt->addHTMLImage('../images/delete.gif');
// $tt->addAttachment('../images/delete.gif','image/gif');
$mime_body = $tt->get();
$mime_hdrs = $tt->headers($headers);
$smtp = Mail::factory('smtp',
array ('host' => $this->host,
'port' => $this->port,
'auth' => false,
'username' => $this->username,
'password' => $this->password));
$recipients=array_merge($to,$cc,$bcc);
$mail = $smtp->send($recipients, $mime_hdrs, $mime_body);
This is all a class code, so initialization is done on the constructor, which is not posted here.
Now my question is, while the above code works fine, i didnt see the correct style on the email sent.
for example if i have this as a message body of my email:
<div style="background-color:silver;">
<h1>MY Header</h1>
</div>
On my email, I can only see the My Header. The background didnt showup as silver.
What did i miss on my code above. Any help ?

Its quite possible that the email provider you are using doesn't allow HTML code in the emails, or it restricts CSS styling in the allowed HTML code. Which email provider are you using?
You might want to test this by sending an email to a gmail.com email address, which does allow html code, and see if it makes any difference.
Another thing to test would be to do a view source, or inspect element if you're using google chrome or firebug in firefox, and see if the html code is being placed where it should be.

Related

Codeigniter 4 Email sending with HTML as message

can you help me figure out a way to use the email class of CI4 to send an email with an HTML as the message?
in Codeigniter 3 it is simple and goes like this:
$email->message($this->load->view('html_page_to_send_from_view_folder',$data,true));
but in Codeigniter 4 I tried doing this:
$email->setMessage(echo view('html_page_to_send_from_view_folder',$data,true));
It gives out an error:
syntax error, unexpected echo(T_ECHO), expecting ')'
I also tried putting the view in a variable like so:
$echo_page = echo view('html_page_to_send_from_view_folder',$data,true);
$email->setMessage($echo_page);
but it just throws the same error, I was searching all over the internet and the documentation but couldn't find a way to do this. Help please.
I tried this but got no error, and also got no email :'(
$echo_page = view('html_page_to_send_from_view_folder',$data,true);
$email->setMessage($echo_page);
According to this, if you want to use some template as your message body, you should do something like this:
// Using a custom template
$template = view("email-template", []);
$email->setMessage($template);
CodeIgniter 4 documentation states:
setMessage($body)
Parameters: $body (string) – E-mail message body
Returns: CodeIgniter\Email\Email instance (method chaining)
Return type: CodeIgniter\Email\Email
Sets the e-mail message body:
$email->setMessage('This is my message');
Okay I got it now I made it work by adding this code $email->setNewLine("\r\n"); at the end just after the setMessage:
$email->setMessage($my_message);
$email->setNewLine("\r\n");
and also I set the SMTP port 587 instead of 465:
$config['SMTPPort']= 587;
ALSO, for the setMessage, I did it like this:
$my_message = view('html_page_to_send_from_view_folder',["id" => $data['id']]);
$email->setMessage($my_message);
really weird man....
A. Firstly,
Instead of:❌
$echo_page = echo view('html_page_to_send_from_view_folder',$data,true);
Use this:✅
$echo_page = view('html_page_to_send_from_view_folder',$data);
Notice the luck of an echo statement and not passing true as the third argument of the view(...) hepler function.
B. Secondly, to submit HTML-based emails, ensure that you've set the mailType property to html. This can be achieved by using the setMailType() method on the Email instance. I.e:
$email->setMailType('html');
Alternatively, you could set the "mail type" by passing an array of preference values to the email initialize() method. I.e:
public function sendMail(): bool
{
$email = \Config\Services::email();
$email->initialize([
'SMTPHost' => 'smtp.mailtrap.io',
'SMTPPort' => 2525,
'SMTPUser' => '479d7c109ae335',
'SMTPPass' => '0u6f9d18ef3256',
'SMTPCrypto' => 'tls',
'protocol' => 'smtp',
'mailType' => 'html',
'mailPath' => '/usr/sbin/sendmail',
'SMTPAuth' => true,
'fromEmail' => 'from#example.com',
'fromName' => 'DEMO Company Name',
'subject' => 'First Email Test',
]);
$email->setTo('to#example.com');
$email->setMessage(view('blog_view'));
$response = $email->send();
$response ? log_message("error", "Email has been sent") : log_message("error", $email->printDebugger());
return $response;
}

Why does Amazon SES fail half the time when called using the PHP SDK?

I'm using the AWS SDK for PHP (version 3.52.33, PHP version 7.2.19) and trying to send emails using the Simple Email Service (SES). I have SES configured, and can run the example code successfully. To make my life easier, I wrote a function to send emails (send_email.php):
<?php
// Path to autoloader for AWS SDK
define('REQUIRED_FILE', "/path/to/vendor/autoload.php");
// Region:
define('REGION','us-west-2');
// Charset
define('CHARSET','UTF-8');
// Specify Sender
define('SENDER', 'sender#xxxx.com');
require REQUIRED_FILE;
use Aws\Ses\SesClient;
use Aws\Ses\Exception\SesException;
function send_email($htmlBody,$textBody,$subject,$recipient) {
$access_key = 'accessKey';
$secret_key = 'secretKey';
$ret_array = array('success' => false,
'message' => 'No Email Sent'
);
$client = SesClient::factory(array(
'version' => 'latest',
'region' => REGION,
'credentials' => array(
'key' => $access_key,
'secret' => $secret_key
)
));
try {
$result = $client->sendEmail([
'Destination' => [
'ToAddresses' => [
$recipient,
],
],
'Message' => [
'Body' => [
'Html' => [
'Charset' => CHARSET,
'Data' => $htmlBody,
],
'Text' => [
'Charset' => CHARSET,
'Data' => $textBody,
],
],
'Subject' => [
'Charset' => CHARSET,
'Data' => $subject,
],
],
'Source' => SENDER,
]);
$messageId = $result->get('MessageId');
$ret_array['success'] = true;
$ret_array['message'] = $messageId;
echo("Email sent! Message ID: $messageId" . "\n");
} catch (SesException $error) {
echo("The email was not sent. Error message: " . $error->getAwsErrorMessage() . "\n");
$ret_array['message'] = $error->getAwsErrorMessage();
}
return $ret_array;
}
This works when called from a simple testing script (test.php) in a terminal:
<?php
ini_set('display_errors','On');
error_reporting(E_ALL | E_STRICT);
require_once './send_email.php';
$email = 'test#email.com';
$htmlbody = 'test';
$txtbody = 'test';
$subject = 'test email';
$success = send_email($htmlbody,$txtbody,$subject,$email);
I get output like:
[~]$ php test.php
Email sent! Message ID: 0101016c8d665369-027be596-f8da-4410-8f09-ff8d7f87181b-000000
which is great. However, I'm doing this to send automated emails from a website (new user registration, password resets, ...) and when I try to use send_email from within a larger script I get a ~%50 success rate (when using a constant email address). Either it works and everything is fine, or it fails without an error message:
The email was not sent. Error message:
I know that an exception is being thrown, as I'm ending up in the catch statement, but I don't know how to get more information about what went wrong since there isn't a message associated with the exception. I've tried expanding what I look for in the catch block:
<snip>
catch (SesException $error) {
echo("The email was not sent. Error message: " . $error->getAwsErrorMessage() . "\n");
$ret_array['message'] = $error->getAwsErrorMessage();
$ret_array['errorCode'] = $error->getAwsErrorCode();
$ret_array['type'] = $error->getAwsErrorType();
$ret_array['response'] = $error->getResponse();
$ret_array['statusCode'] = $error->getStatusCode();
$ret_array['isConnectionError'] = $error->isConnectionError();
}
but when it fails everything is NULL except isConnectionError = false. Anecdotally, it is totally random -- I haven't been able to discern a pattern at all as to when it works and when it fails.
One other potentially relevant note: if I loop the email sending so a new user gets 10 emails, either they all succeed or they all fail.
So, does anyone have any suggestions as to what might be going wrong, or other steps I could take to help diagnose why this is happening?
For anyone running in to a similar issue in the future, I eventually came up with two solutions:
Initially, I gave up hope on the AWS SDK and switched to using PHPMailer which avoided the issue (though I believe at the cost of a loss in performance).
The real issue (I'm fairly certain now) was a mismatch in the versions of PHP between my CLI and what the webserver was providing. This question got me thinking about how that might be the issue. By updating the version of cURL and PHP that the webserver was using, I resolved the issue.

Accept email address from user and send email to that address

public function send_mail() {
$this->email->from('your#email.com', 'My Name');
$this->email->to('to#email.com');
$this->email->cc('cc#email.com');
$this->email->subject('Email Test');
$this->email->message('Testing the email class.');
$this->email->send();
echo $this->email->print_debugger();
}
i'm trying out the codeigniter email func but i cant seem to receive the test mail, but it saids that it has successfully send the mail but there's none,
new to ci so i'm confused about this problem, $this->load->library('email'); is also loaded,
anyhelp thanks!
EDIT
ok guys thanks for the answer i have added the ff code and it now works,
$config = Array(
'protocol' => 'smtp',
'smtp_host' => 'ssl://smtp.googlemail.com',
'smtp_port' => 465,
'smtp_user' => 'your email',
'smtp_pass' => 'your password'
);
Now my question is how will I edit the codes above to accept the "to" email from the user?
okay i did the "to" part already, and its like this
$this->email->to($point->email);
need help again with the "message" part, i need to put data from the user in the "message" part, i tried what i did in the "to" part but it only accepts one item, i need multiple items, thanks
In the section where you're calling the function send_mail(), pass the email address and other data as well, as arguments to the function; something like this:
$to = $point->email;
$msg = $point->message; // the message part
$phone = $point->phone; // phone number
$address = $point->address; // postal address
$this->send_email($to, $msg, $phone, $address);
And then slightly modify the send_mail() function as:
// $to_address will contain the value stored in $to, i.e. "abc#def.com" in this case
public function send_mail($to_address, $body_message, $phone_no, $addr) {
// can make use of extra data like phone number, address in here
$this->email->from('your#email.com', 'My Name');
$this->email->to($to_address);
$this->email->message($body_message);
.
.
.
}
It works fine in my linux server without any $config.
Please read this to set another protocol

Mandrill inbound emails through Laravel / PHP

I was wondering if someone could help me with a problem I have been having some trouble researching related to Laravel and inbound email processing through Mandrill.
Basically I wish to be able to receive emails through Mandrill and store them within my Laravel database. Now i'm not sure if i'm reading through the documentation with the wrong kind of eyes, but Mandrill says it deals with inbound email as well as outbound, however i'm starting to think that Mandrill deals with inbound email details as opposed to the actual inbound email, such as if the message is sent etc.
I've created a new Mandrill account, created an API key, created an inbound domain and corresponding subdomain of my site (e.g. inboundmail.myproject.co.uk), set the MX record and the MX record is showing as valid. From there i have set up a route (e.g. queries#inboundmail.myproject.co.uk), and a corresponding webhook (myproject.co.uk/inboundmail.php) and within this webhook tried a variety of the examples given in the API (https://mandrillapp.com/api/docs/inbound.php.html), such as adding a new route, checking the route and attempting to add a new domain. All of them worked and produced the correct results, so my authentication with Mandrill is not in question, but my real question is is there a specific webhook for dealing with accepting incoming mail messages?
I cant help but feel like an absolute idiot asking this question as i'm sure the answer is either staring me in the face or just not possible through Mandrill.
Thanks in advance.
Thanks to duellsy and debest for their help, in the end i found a script and expanded on it to add the mail to my own database and style / display it accordingly. Hope this helps someone who may have the same trouble:
<?php
require 'mandrill.php';
define('API_KEY', 'Your API Key');
define('TO_EMAIL', 'user#example.com');
define('TO_NAME', 'Foo Bar');
if(!isset($_POST['mandrill_events'])) {
echo 'A mandrill error occurred: Invalid mandrill_events';
exit;
}
$mail = array_pop(json_decode($_POST['mandrill_events']));
$attachments = array();
foreach ($mail->msg->attachments as $attachment) {
$attachments[] = array(
'type' => $attachment->type,
'name' => $attachment->name,
'content' => $attachment->content,
);
}
$headers = array();
// Support only Reply-to header
if(isset($mail->msg->headers->{'Reply-to'})) {
$headers[] = array('Reply-to' => $mail->msg->headers->{'Reply-to'});
}
try {
$mandrill = new Mandrill(API_KEY);
$message = array(
'html' => $mail->msg->html,
'text' => $mail->msg->text,
'subject' => $mail->msg->subject,
'from_email' => $mail->msg->from_email,
'from_name' => $mail->msg->from_name,
'to' => array(
array(
'email' => TO_EMAIL,
'name' => TO_NAME,
)
),
'attachments' => $attachments,
'headers' => $headers,
);
$async = false;
$result = $mandrill->messages->send($message, $async);
print_r($result);
} catch(Mandrill_Error $e) {
// Mandrill errors are thrown as exceptions
echo 'A mandrill error occurred: ' . get_class($e) . ' - ' . $e->getMessage();
// A mandrill error occurred: Mandrill_PaymentRequired - This feature is only available for accounts with a positive balance.
throw $e;
}
?>
Like using webhooks from other mail parsing services, you'll need to make use of
file_get_contents("php://input")
This will give you the raw data from the webhook, which you can then json_decode and work with the results.

How to apply template (tpl) file for email message body

I've this mail function in my custom module
function mymodule_mail($key, &$message, $params) {
switch ($key) {
case 'notification':
$message['headers']['Content-Type'] = 'text/html; charset=UTF-8; format=flowed';
$message['subject'] = $params['subject'];
$message['body'] = t('<table style="border:2px solid black;"><tr><td>MESSAGE BODY </td><td><b>'.$params['msg'].'</b></td></tr></table>');
break;
}
}
Here you can clearly see that for message body i'm using some html tags.
Below code invoke the mail function, which is written in my block.
$params = array(
'subject' => 'email subject',
'msg' => 'message body',
);
drupal_mail('mymodule', 'notification', 'email address', language_default(), $params);
I want to know, is there any easy way to apply a template (.tpl.php) file for my message body so that i can put my all css styling within that tpl file.
Any suggestion would be greatly appreciated.
You'll need to set up a theme call for it
function mymodule_theme() {
$path = drupal_get_path('module', 'mymodule') . '/templates';
return array(
'mymodule_mail_template' => array(
'template' => 'your-template-file', //note that there isn't an extension on here, it assumes .tpl.php
'arguments' => array('message' => ''), //the '' is a default value
'path' => $path,
),
);
}
Now that you have that, you can change the way you're assigning the body
$message['body'] = theme('mymodule_mail_template', array('message' => $params['msg']);
The key message needs to match the argument you supplied in mymodule_theme(), which it does.
Now you can just create your-template-file.tpl.php in the module's templates/ folder (you'll have to make that) and you can use the variable $message in your template to do whatever you'd like. The variable name matches your theme argument name.
After your module is set up properly, make sure to flush the cache. I can't tell you how long it took me to realize that the first time I started working with Drupal, and how much time I wasted trying to fix non-existent bugs.
The HTML Mail module does just that :-)

Categories