Gmail API with PHP mailer can't send multiple attachments - php

I am using PHPmailer with Gmail API to send out mail. This process has worked very well for me for sending just standard emails, however, I want to also have the ability to send out an email with attachments using the Gmail API. When I tried using $mail->addAttachment($urlString, $name); Gmail would come back with the error Request Entity Too Large Error 413 (The size of the attachments never goes above 20MB so it should be well within the 35MB limits of Gmail API).
After some searching, I found out it was because I wasn't using "/Upload URI" for sending large Gmail Attachments (Anything above 5mb and below 35mb). Problem is, I am not very knowledgeable on how to work the Gmail API and only got what I have now from basically copying code from somewhere else and slightly modifying it for my uses and as such, I have no idea how to change the URI like that.
Here is what I have so far, that works with standard emails:
function($agent, $assistantName='', $assistantEmail='', $subject, $body, $attachments=''){
$key = realpath(dirname(__FILE__).'/Services/Google/Gmail.json');
$useremail = 'myuseremail#example.com';
$toAddress = $agent->email;
$agentFirst = $agent->first_name;
$client = new Google_Client();
putenv('GOOGLE_APPLICATION_CREDENTIALS='.$key);
$client->useApplicationDefaultCredentials();
$user_to_impersonate = $useremail;
$client->setSubject($user_to_impersonate);
$client->addScope('https://www.googleapis.com/auth/gmail.compose');
if ($client->isAccessTokenExpired()) {
$client->refreshTokenWithAssertion();
}
//prepare the mail with PHPMailer
$mail = new PHPMailer();
$mail->CharSet = "UTF-8";
$mail->Encoding = "base64";
$subject = $subject;
$msg = $body;
$from = $useremail;
$fname = "My Name";
$mail->From = $from;
$mail->FromName = $fname;
$mail->AddAddress($toAddress, $agentFirst);
$mail->AddCC($assistantEmail, $assistantName);
$mail->AddReplyTo($from,$fname);
if ($attachments != '') {
foreach ($attachments as $name => $urlString) {
$mail->addAttachment($urlString, $name);
}
}
$mail->Subject = $subject;
$mail->Body = $msg;
$mail->IsHTML(true);
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
$m = new Google_Service_Gmail_Message();
$data = base64_encode($mime);
$data = str_replace(array('+','/','='),array('-','_',''),$data); // url safe
$m->setRaw($data);
$service = new Google_Service_Gmail($client);
$email = $service->users_messages->send($useremail, $m);
return json_encode($email);
}
I don't really know where to go from here, so any help would be appreciated.

use EZCMail and build the email structure yourself... it is very pickey! I can post some details after.
you may also have to send the email in chunks.
If the email is over 4MB then you are going to have to send in chunks using Google_Http_MediaFileUpload
Your code using this should be something similar to this, there is examples for using Google_Http_MediaFileUpload elsewhere on the web which might be more complete:
$client->setDefer(true);
// Call the API with the media upload, defer so it doesn't immediately return.
$arrRequestParams = $arrRequestParams+['uploadType' => 'multipart'];
$result = $this->TransportPrepSwitch($strAction, $objGMessage, $arrRequestParams); // Make draft or message $service->users_messages->send('me', $objGMessage, $arrRequestParams);
$mailMessage = base64url_decode($strRaw);
// create mediafile upload
$chunkSizeBytes = 1*1024*1024; // send to google in 1MB chunks
$media = new Google_Http_MediaFileUpload($client,$result,'message/rfc822',$mailMessage,true,$chunkSizeBytes);
$media->setFileSize(strlen($mailMessage));
// Upload chunks. Status will contain the completed $result.
$status = false;
set_time_limit(300);
while(!$status)
$status = $media->nextChunk();
// Reset to the client to execute requests immediately in the future.
$client->setDefer(false);
$objResponce = $status;
Also the structure of the email parts MUST be as follows:
multipart/mixed => [
multipart/related => [
multipart/alternative => [
plain,
html
],
inline images,
],
attachments,
]
The only way I could achieve this was using EZCMail to build the email part by part.

Related

How to send custom message before, proxy session send actual message

When Customer replies to proxy service reserved number then proxy hit an OutOfSessionCallbackUrl(if a session is not active).
That URL will come to my code below.
public function response()
{
$to = $_POST['To'];
$from = $_POST['From'];
$from = substr($from, 2);
$body = $_POST['Body'];
$twilio = new Client($this->sid, $this->token);
$response=$this->db->get_where('contact_management as cm
,proxy_service as ps',
array('mobile'=>$from,'company_mobile'=>$to,'sc.sms_template_id<>'=>0))
->row_array();
$number = trim($response['country_code'].$response['mobile_number']);
//Here I'm sending a response
header("content-type:application/json");
?>
{
"uniqueName": "<?php echo rand();?>",
"ttl":"64800",
"mode": "voice-and-message",
"participantIdentifier":"<?php echo $number;?>"
}
<?php
}
This will create a session between SMS sender and returned number(company) and send the message of the sender to the company. I want to send a custom message before Twilio proxy send actual message to the company.
Thanks.
Twilio developer evangelist here.
Currently you are using the out of session callback in order to create a session, but you want to send a message before you forward on the incoming message.
To do this, you won't be able to respond with the JSON to create a session. Instead, you should create the session manually using the session API. Once you have created a session you can then send your initial message by creating an interaction on the participant you want to send the message to. You can then follow up by using the same API to forward the original message. And finally you still need to respond to the webhook. Since you handled all the message sending manually, you can return an empty TwiML <Response/> to signify that you need Twilio to take no further part.
Let me know if that helps at all.
Here Are the complete Description.
I have add Twilio number as reserved in proxy service and set the proxy service OutOfSessionCallbackUrl.When this URL reach my code then the magic happens,
public function response()
{
$to = $_POST['To'];
$from = $_POST['From'];
$twilio = new Client($this->sid, $this->token);
$response=$this->db->get_where('contact_management ,proxy_service,
array('mobile'=>$from,'company_mobile'=>$to))->row_array();
$service_sid=$response['service_sid'];
$session = $twilio->proxy->v1->services($service_sid)->sessions
->create(array("uniqueName" => rand(),"ttl"=>"64800"));
$session_sid = $session->sid;
$participant1 = $twilio->proxy->v1->services($service_sid)
->sessions($session_sid)->participants->create($_POST['From'], // identifier
array("friendlyName" => $response['f_name'],"proxyIdentifier"=>$to));
$from_id = $participant1->proxyIdentifier;
$participant2 = $twilio->proxy->v1->services($service_sid)
->sessions($session_sid)->participants
->create($response['country_code'].$response['mobile_number'], // identifier
array("friendlyName" => $response['first_name']));
$to_id = $participant2->proxyIdentifier;
$to_sid = $participant2->sid;
$body = $response['campaign_name']."\n";
$body .= $_POST['Body'];
$message_interaction = $twilio->proxy->v1->services($service_sid)
->sessions($session_sid)
->participants($to_sid)
->messageInteractions
->create(array("body" => $body));
header("content-type:text/xml");
?>
<Response />
<?php
}

Error 413: Request Entity Too Large with PHP

I'm using Gmail's PHP API to send emails. Using those resources, I can send messages with attachments upto 5 mb.
But I can't figure out how to send attachments larger than 5 MB. I've found that it is necessary to use multipart uploadtype, but I can not figure out exactly how to implement that based on what I tried is:
$service->users_messages->send($userId, $message, 'uploadType' => 'resumable']);
$service->users_messages->send($userId, $message, 'uploadType' => 'multipart']);
still getting Error 413: Request Entity Too Large
Already researched on internet but not able to make it working.
Edit: Below codes give me Request is too large. even for 5 mb file
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
$raw = rtrim(strtr(base64_encode($mime), '+/', '-_'), '=');
$message = new Google_Service_Gmail_Message();
$message->setRaw($raw);
$message->setThreadId($threadId); //only for reply
$sendOptions = [
'uploadType' => 'resumable'
];
// size of chunks we are going to send to google
$chunkSizeBytes = 1 * 1024 * 1024;
$client->setDefer(true);
$response = $service->users_messages->send($userId, $message, $sendOptions);
// create mediafile upload
$media = new Google_Http_MediaFileUpload(
$client,
$response,
'message/rfc822',
$raw,
true,
$chunkSizeBytes
);
$media->setFileSize(strlen($raw));
// Upload the various chunks. $status will be false until the process is complete.
$status = false;
while (! $status) {
$status = $media->nextChunk();
echo $status ."<br>";
}
// Reset to the client to execute requests immediately in the future.
$client->setDefer(false);
// Get sent email message id
$googleMessageId = $status->getId();
Here they suggest to Remove $message->setRaw($raw); . If I remove this line than I get Recipient address required error.
How I fixed it:
$mail = new PHPMailer();
$mail->CharSet = 'UTF-8';
$mail->Subject = $subject;
$mail->Body = $body;
$mail->IsHTML(true);
$mail->addAddress($to);
$mail->AddCC($cc);
$mail->AddBCC($bcc);
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
$sendOptions = [ 'uploadType' => 'resumable' ];
$client->setDefer(true);
$chunkSizeBytes = 1 * 1024 * 1024;
// create mediafile upload
$media = new Google_Http_MediaFileUpload(
$client,
$response,
'message/rfc822',
$mime,
true,
$chunkSizeBytes
);
$response = $service->users_messages->send($userId, $message);
$media->setFileSize(strlen($mime));
// Upload the various chunks. $status will be false until the process is complete.
$status = false;
while (! $status) {
$status = $media->nextChunk();
}
//Reset to the client to execute requests immediately in the future.
$client->setDefer(false);
// Get sent email message id
$googleMessageId = $status->getId();

Call to undefined method Google_Service_Gmail_Message::toSimpleObject()

I'm trying to develop a web application that send email throught Gmail API.
But I'm getting this error :
Call to undefined method Google_Service_Gmail_Message::toSimpleObject()
Here is my code :
// LOAD GOOGLE LIBRARY
$this->CI->load->library('master_google');
$this->CI->load->library('master_phpmailer');
$client = $this->CI->master_google->getClient($data);
$mail = $this->CI->master_phpmailer;
$mail->setFrom($data->sender_email, $data->sender_name);
$mail->addReplyTo($data->response_email, $data->response_name);
$mail->addAddress($data->email);
$mail->Subject = $data->subject;
$mail->msgHTML(htmlspecialchars_decode($data->body));
$mail->preSend();
$mime = $mail->getSentMIMEMessage();
$encoded_message = base64url_encode($mime);
// Gmail Message Body
**$message = new Google_Service_Gmail_Message();**
$message->setRaw($encoded_message);
// Send the Email
$service = new Google_Service_Gmail($client);
$email = $service->users_messages->send('me',$message);
if($email->getId()){
return array('stat' => true, 'msg' => '');
} else {
return array('stat' => false, 'msg' => '');
}
The error is generated on this line :
$message = new Google_Service_Gmail_Message();
Any help is appreciated.
I found what was the problem lol, I had a model with the same name : Google_model, I rename that to Mygoogle_model and it works :D
I think the method toSimpleObject() does not exist in your gmail-api class.

Error sending more than 300 emails with PHP Swift Mailer showing Internal Server Error

Error sending more than 300 emails with PHP Swift Mailer showing Internal Server Error getting only 200 mails out of 300
i am using ftp surfer
another problem is after sending 200 mails upto one hour mails are not going it showing us as send but i am not getting any mails after one hour again they are getting
mail ids are getting from mysql database
using for each loop mails are sending
<?php // Create the message
// Create the message
$message = Swift_Message::newInstance();
$sql=mysql_query("select * from test_email where status=''");
while($row=mysql_fetch_array($sql))
{
// Usually you want to replace the following static array
// with a dynamic one built retrieving users from the database
$users = array(
array(
"fullname" => "Aurelio De Rosa",
"operations" => $row['sno'],
"email" => $row['email']
)
);
// Create the replacements array
$replacements = array();
foreach ($users as $user) {
$replacements[$user["email"]] = array (
"{fullname}" => $user["fullname"],
"{transactions}" => $user["operations"]
);
}
// Create the mail transport configuration
$transport = Swift_MailTransport::newInstance();
// Create an instance of the plugin and register it
$plugin = new Swift_Plugins_DecoratorPlugin($replacements);
$mailer = Swift_Mailer::newInstance($transport);
$mailer->registerPlugin($plugin);
// Create the message
$message = Swift_Message::newInstance();
$message->setSubject("This email is sent using Swift Mailer");
// Create your file contents in the normal way, but don't write them to disk
// Create your file contents in the normal way, but don't write
//them to disk
$type = $message->getHeaders()->get('Content-Type');
$type->setValue('text/html');
$type->setParameter('charset', 'utf-8');
// Use AntiFlood to re-connect after 100 emails
$mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100));
// And specify a time in seconds to pause for (30 secs)
$mailer->registerPlugin(new Swift_Plugins_AntiFloodPlugin(100, 30));
// Create the message
$message = Swift_Message::newInstance('My subject');
// Set the body
$message->setBody(
'<html>' .
' <head></head>' .
' <body>' .
' Here is an image <img src="http://www.graymatter8.info/Developer1/swiftm/x.php?ts={transactions}&&ip='.$ip.'" alt="" width="1" height="1" border="0"/>' .
' Rest of message' .
' </body>' .
'</html>',
'text/html' // Mark the content-type as HTML
);
$message->setFrom("account#bank.com", "Testing");
$failedRecipients = array();
$numSent = 0;
// Send the email
foreach($users as $user)
{
$message->setTo($user["email"], $user["fullname"]);
$mailer->send($message);
}
?>
You should send it out in packets, like 10-20 at once. As soon as a package is done, you can go to the next 10-20, and so on...

Error when Sending Mail with Attachments Using PEAR

My page continues to error out (Error 324 - Chrome) when attempting to send e-mails with attachments using PHP's PEAR Mail extension. Although the page error's out - I do receive one of the approximately 800 e-mails. Here's what I'm working with:
function email_statements($type) {
switch($type) {
// Determine the type of statement to be e-mailed
case 'monthly':
// Array holding all unique AP e-mail addresses
$ap_email_addresses = array();
include('../path/to/db/connection/params.php');
// Grab the unique AP e-mail address set to receive statements
$stmt = $mysqli->prepare("SELECT email FROM statements GROUP BY email ORDER BY email ASC");
$stmt->execute();
$stmt->bind_result($ap_email_address);
// Add unique e-mail address to AP E-mail Addresses array
while($row = $stmt->fetch()) $ap_email_addresses[] = $ap_email_address;
$stmt->close();
$mysqli->close();
// Verify we grabbed the e-mail addresses
if(count($ap_email_addresses) == 0) {
// Exit and return error code if unable to grab e-mail addresses
$return_message = 1;
exit;
}
// E-mail addresses grabbed - proceed
else {
// PDF formatted date
date_default_timezone_set('America/New_York');
$formatted_date = date('m_d_Y');
// Now we have the unique e-mail addresses - associate those with the account numbers
include('../path/to/db/connection/params.php');
foreach($ap_email_addresses as $email_address) {
$file_names = array();
$stmt = $mysqli->prepare("SELECT customer_number FROM statements WHERE email = ?");
$stmt->bind_param("s", $email_address);
$stmt->execute();
$stmt->bind_result($ap_account_number);
// Constructs the name of the statement (PDF) file to be sent
while($output = $stmt->fetch()) $file_names[] = $ap_account_number . '_' . $formatted_date . '.pdf';
// Send e-mails
include('Mail.php');
include('Mail/mime.php');
// Include SMTP authentication parameters
include('../path/to/email/info.php');
// Set the e-mail recipients
$recipients = 'example#example.com';
// Set the e-mail subject
$subject = 'Monthly Account Statement';
// Create the e-mail body
$html =
'<html>
<body>
<p>Test E-mail</p>
</body>
</html>';
// Construct the message headers
$headers = array(
'From' => $from,
'Subject' => $subject,
'Content-Type' => 'text/html; charset=UTF-8',
'MIME-Version' => '1.0'
);
$mimeparams = array();
$mimeparams['text_encoding'] = '8bit';
$mimeparams['text_charset'] = 'UTF-8';
$mimeparams['html_charset'] = 'UTF-8';
$mimeparams['head_charset'] = 'UTF-8';
// Create a new instance
$mime = new Mail_mime();
// Specify the e-mail body
$mime->setHTMLBody($html);
// Attach the statements (PDF)
foreach($file_names as $attached_file) {
$file = '../path/to/the/pdf/file/' . $attached_file;
$file_name = $attached_file;
$content_type = "Application/pdf";
$mime->addAttachment ($file, $content_type, $file_name, 1);
}
// Create the body
$body = $mime->get($mimeparams);
// Add the headers
$headers = $mime->headers($headers);
// Create SMTP connect array to be passed
$smtp = Mail::factory('smtp', array ('host' => $host, 'port' => $port, 'auth' => true, 'username' => $username, 'password' => $password));
// Send the message
$mail = $smtp->send($recipients, $headers, $body);
if(PEAR::isError($mail)) echo 'Error';
else echo 'Sent';
// Close this account and cycle through the rest
$stmt->close();
}
$mysqli->close();
}
break;
}
}
Now I thought maybe I wasn't giving the script enough time to execute - so I set it ridiculously high set_time_limit(99999999) to ensure it had plenty of time, although it normally times out within 10-15 seconds. So basically it works like this, I have an internal DB that stores customer account numbers and e-mail addresses. Accounts can have the same e-mail address (It's sent to their company's AP department) - aka one e-mail address receives statements for multiple branches. From their each statement is already constructed with the format being ACCOUNTNUMBER_MM_DD_YYYY.pdf.
So I'm simply trying to have a short message in the body, and attach the monthly statements. Again, not sure why it's failing, and even though the script halts, I do receive ONE of the e-mails (I'm sending them all to myself at the moment just to test). Can anyone see where I may have an issue?
I discovered the issue. As of PHP 5.0+ you cannot have multiple instances of the same include file - aka Mail.php was included as it looped. Once it was moved outside of the loop, the issue was resolved.

Categories