2

I'm using Google's PHP client library to send calls to Gmail's API. Using those resources, I can send messages with attachments using code like this:

public function send_message(Google_Service_Gmail $gmail, $raw_message)
{
    Log::info('Gmail API request \'users_messages->send\'');
    $postBody = new Google_Service_Gmail_Message();
    $postBody->setRaw(Str::base64_encode_url($raw_message));
    return $gmail->users_messages->send('me', $postBody, ['uploadType' => 'multipart']);
}

But I can't for the life of me figure out how send attachments larger than a few MB. I've found that it is necessary to use multipart uploadtype, but I can figure out exactly how to implement that based on what I currently have, as the code above still gives me this error:

Error calling POST https://www.googleapis.com/gmail/v1/users/me/messages/send?uploadType=multipart
Error 413: Request Entity Too Large

This article has really good broad strokes information, but I'm hoping for a little bit more guidance specific to Google's PHP client library.

EDIT: According to this page, the maximum upload size is actually 35 MB. The size specified in my php.ini is sufficient for this, and the requests fails as a 413 from google, not an internal server error.

Community
  • 1
  • 1
johncorser
  • 9,262
  • 17
  • 57
  • 102
  • I'm not 100% sure, but I think there is a generell limit of 4MB at gmail. The multipart upload is just enabling you to send meta data and media with one request. (Tell me if I'm wrong...) – marfis Mar 16 '15 at 16:48
  • this has to be a google limitation otherwise you could have gone into php.ini conf on your server and increased the post size limit to whatever size. – unixmiah Mar 16 '15 at 17:12
  • According to [this page](https://developers.google.com/gmail/api/v1/reference/users/messages/send), the maximum upload size is actually 35 MB. The size specified in php.ini is sufficient for this, and the requests fails as a 413 from google, not an internal server error. – johncorser Mar 16 '15 at 19:57

2 Answers2

3

If you have already prepared raw email, you can use this example (originally taken from here):

// size of chunks we are going to send to google    
$chunkSizeBytes = 1 * 1024 * 1024;

// actual raw email message
$mailMessage = 'raw email text with files embedded'

// code to create mime message
$googleClient = new Google_Client();

// code to setup the client
$mailService = new Google_Service_Gmail($googleClient);
$message = new Google_Service_Gmail_Message();

// Call the API with the media upload, defer so it doesn't immediately return.
$googleClient->setDefer(true);

$request = $mailService->users_messages->send('me', $message);

// create mediafile upload
$media = new Google_Http_MediaFileUpload(
    $googleClient,
    $request,
    'message/rfc822',
    $mailMessage,
    true,
    $chunkSizeBytes
);
$media->setFileSize(strlen($mailMessage));

// 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.
$googleClient->setDefer(false);

// Get sent email message id
$googleMessageId = $status->getId();
dikirill
  • 1,873
  • 1
  • 19
  • 21
  • What I don't understand is where is your actual file being represented in the code? – LargeTuna Dec 05 '17 at 22:54
  • @LargeTuna it's coming from $mailMessage, it must be a raw email text. – dikirill Dec 07 '17 at 22:13
  • 1
    OMG!!! Your wisdom englightened me. Thank you DEEPLY. But seriously, thank you so mucho! Perfect example. IT WORKS. – Martin Zvarík Dec 13 '18 at 01:00
  • 1
    I wish I could give you 100 likes – Martin Zvarík Dec 13 '18 at 01:01
  • This gives me an error about the request being too large. This occurs in the first API call the SDK makes, to get the resumable URL for the upload. For some reason the body it's passing is "too large" for that request. The MIME message is about 12mb in my case. – fideloper Nov 11 '21 at 19:30
1

Not too familiar with the GMail API, but you should be able to use chunked uploads to reduce the size of each individual request. Take a look at the file upload sample in the client Github: https://github.com/google/google-api-php-client/blob/master/examples/fileupload.php#L73

$media = new Google_Http_MediaFileUpload(
  $client,
  $request,
  'text/plain',
  null,
  true,
  $chunkSizeBytes
);

$media->setFileSize(filesize(TESTFILE));
$status = false;
$handle = fopen(TESTFILE, "rb");
while (!$status && !feof($handle)) {
  $chunk = fread($handle, $chunkSizeBytes);
  $status = $media->nextChunk($chunk);
}
Ian Barber
  • 19,765
  • 3
  • 58
  • 58
  • 1
    This worked. And really, not too familiar with the gmail api? You are a [contributor to the php client](https://github.com/ianbarber) and [mentioned in the source code](https://github.com/google/google-api-php-client/blob/master/src/Google/Service/Resource.php#L72) of methods that I'm using in my app! – johncorser Mar 18 '15 at 15:08
  • 1
    Oh yeah, I'm familiar with the client, but not the gmail API specifically :) – Ian Barber Mar 20 '15 at 02:41