Mailgun发送带附件的邮件。

12

我在使用Mailgun发送包含附件的邮件时遇到了问题。 如果有人做过这个,请回复。 这是我的代码...

$mg_api = 'key-3ax6xnjp29jd6fds4gc373sgvjxteol0';
$mg_version = 'api.mailgun.net/v2/';
$mg_domain = "samples.mailgun.org";
$mg_from_email = "info@samples.com";
$mg_reply_to_email = "info@samples.org";

$mg_message_url = "https://".$mg_version.$mg_domain."/messages";


$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);

curl_setopt ($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt ($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_VERBOSE, 0);
curl_setopt ($ch, CURLOPT_HEADER, 1);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 10);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);

curl_setopt($ch, CURLOPT_USERPWD, 'api:' . $mg_api);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

curl_setopt($ch, CURLOPT_POST, true); 
//curl_setopt($curl, CURLOPT_POSTFIELDS, $params); 
curl_setopt($ch, CURLOPT_HEADER, false); 

//curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
curl_setopt($ch, CURLOPT_URL, $mg_message_url);
curl_setopt($ch, CURLOPT_POSTFIELDS,                
        array(  'from'      => 'aaaa <' . 'aaa@aaa.com' . '>',
                'to'        => 'test.client91@gmail.com',
                'h:Reply-To'=>  ' <' . $mg_reply_to_email . '>',
                'subject'   => 'aaaaa'.time(),
                'html'      => 'aaaaaa',
                'attachment'[1] => 'aaa.rar'
            ));
$result = curl_exec($ch);
curl_close($ch);
$res = json_decode($result,TRUE);
print_r($res);
我已经使用了我的Mailgun设置。 我能收到电子邮件,但是没有附件。如果我使用URL路径,则会显示URL,而不是附件。
9个回答

9

我知道这是旧的内容,但我最近遇到了这个问题,而这篇文章几乎是我在互联网上能找到的唯一信息。因此,我希望这将对其他人有所帮助。在与MailGun支持团队交谈后,我发现以下代码适用于当前的API。

循环通过零到n个附件文件的数组:

    $attachmentsArray = array('file1.txt', 'file2.txt');
    $x = 1;
    foreach( $attachmentsArray as $att )
    {
        $msgArray["attachment[$x]"] = curl_file_create( $att );
        $x ++;
    }

    // relevant cURL parameter, $msgArray also contains to, from, subject  parameters etc.
    curl_setopt($ch, CURLOPT_POSTFIELDS,$msgArray);

澄清一下,此示例未使用Composer,而MailGun SDK需要使用它。这是通过PHP/cURL访问MailGun API的方式。 - nzmuzzer
这需要 PHP 5.5 或更高版本(因此之前没有被提出作为解决方案的原因)。 - bart

7

1
你的示例需要使用Composer。 - Will Bowman
3
@user1964269 可以将附件作为直接链接而不是本地文件吗?例如像 attachment[1]' => '@http://example.com/direc/file/path/file.jpg 这样的格式? - Khurshid Alam
6
顺便说一下,上面的Mailgun文档链接无法使用,因为Mailgun没有将.net链接重定向到.com,哈哈...这个链接可以使用:https://documentation.mailgun.com/user_manual.html#sending-via-api - Patrick Steil

4

文档没有明确说明,但是附件本身被打包成multipart/form-data格式并作为请求的一部分。

调试问题的最佳方法是使用Fiddler来监视请求。请确保接受Fiddler的根证书,否则由于SSL错误请求将无法发出。

在Fiddler中,您应该看到以下头文件:

Cookies / 登录

Authorization: Basic <snip>==

实体

Content-Type: multipart/form-data; boundary=<num>

对于TextView:

Content-Disposition: form-data; name="attachment"
@Test.pdf

Content-Disposition: form-data; name="attachment"; filename="Test.pdf"
Content-Type: application/pdf
<data>

请注意,你需要POST字段'attachment=@'。对于form-data,字段名也是'attachment',然后有'filename='(没有'@'),最后是文件内容。
我认为CURL应该会根据使用'@'语法并指定本地机器上文件的路径来自动完成所有这些操作。但不知道其神奇行为,很难理解实际发生的事情。
例如,在C#中,代码如下:
public static void SendMail(MailMessage message) {
    RestClient client = new RestClient();
    client.BaseUrl = apiUrl;
    client.Authenticator = new HttpBasicAuthenticator("api", apiKey);

    RestRequest request = new RestRequest();
    request.AddParameter("domain", domain, ParameterType.UrlSegment);
    request.Resource = "{domain}/messages";
    request.AddParameter("from", message.From.ToString());
    request.AddParameter("to", message.To[0].Address);
    request.AddParameter("subject", message.Subject);
    request.AddParameter("html", message.Body);

    foreach (Attachment attach in message.Attachments)
    {
        request.AddParameter("attachment", "@" + attach.Name);
        request.AddFile("attachment",
            attach.ContentStream.WriteTo,
            attach.Name,
            attach.ContentType.MediaType);
    }

    ...
    request.Method = Method.POST;
    IRestResponse response = client.Execute(request);
}

嘿,你有没有用过Mailgun Web API?我在使用Web API发送附件时遇到了一些问题。 - therealprashant

3
我曾经因为这个问题卡住了一段时间,这里的答案对我很有帮助,但是我发现了一个未被提及的事情。
我一直使用空/NULL值发送POST参数,例如:$post_data['cc'] = NULL。这不会阻止我发送纯文本邮件(无附件),但是当我尝试发送带有附件的电子邮件时就出现了问题。从数组中删除空白的cc解决了部分问题。
此外,在PHP curl中发布数据之前,我一直在使用http_build_query,这导致我的带附件的电子邮件发送失败。
删除空的cc和http_build_query对我有用。也许这是一个不常见的情况,但是如果对于其他人有所帮助,我想分享这个问题。

刚刚验证了使用Mailgun API时的崩溃情况,日期为2020年8月8日,当使用http_build_query时:千万不要使用它! - centurian

0

这对我有用...

class Email {

    function send($array, $file_array) {
        $mgClient = new Mailgun('YOUR_MAILGUN_API_KEY');
        $domain = "mg.YOUR_DOMAIN.com";
        $result = $mgClient->sendMessage($domain, $array, array('attachment' => $file_array));
        return $result;
    }   
}

$array = array(
    'from'    => 'From <from@from.com>',
    'to'      => 'To <to@to.com>',
    'subject' => 'Your Subject',
    'html'    => '<h1>Hooray!</h1>',
);

$file_array = array('/var/www/scripts/test.csv');
echo json_encode($Email::send($array, $file_array));

0

这对我来说运行良好。

require '../../vendor/autoload.php';
use Mailgun\Mailgun;

# Instantiate the client.
$mgClient = new Mailgun('key-b0e955');
$domain = "domain.com";

# Make the call to the client.
$result = $mgClient->sendMessage("$domain",
  array('from'    => '<postmaster@domain.com>',
        'to'      => '<test@gmail.com>',
        'subject' => 'csv file',
        'text' => 'csv test file'
       ),array('attachment' => [
    ['remoteName'=>'student.csv', 'filePath'=>'/form/stu.csv']
  ]) );

0

添加附件文件:

"attachment[1]" = "@$_FILES['careerDocument']['tmp_name'];filename=test.jpg".
($contentType ? ';type=' . $contentType : '' ) ;
curl_setopt($ch, CURLOPT_POSTFIELDS, ($message));

0

这对我有用:

<?php

$filePath='@Wealth_AC_AMF.pdf';

$curl_post_data=array(
    'from'    => 'Excited User <noreply@test.com>',
    'to'      => 'test@gmail.com',
    'subject' => 'Hello',
    'text'    => 'test',
'attachment[1]' => $filePath
);

$service_url = 'https://api.mailgun.net/v3/test.com/messages';
$curl = curl_init($service_url);
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($curl, CURLOPT_USERPWD, "api:key-test"); 

curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);

curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post_data);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 


$curl_response = curl_exec($curl);  
$response = json_decode($curl_response);
curl_close($curl);

var_dump($response);



 ?>

...你可以扩展你的数组:'attachment[2]' => $filePath2,等等。 - centurian

0

这对我有用。我已经在附件数组中传递了附件文件的URL。现在我可以在电子邮件中发送多个附件。

$attachment = [ 0 => 'https://www.crm.truerater.com/public/assets/client_upload_images/1634327873.png', 1 => 'https://www.crm.truerater.com/public/assets/client_upload_images/1634327873.png' ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, 'https://api.mailgun.net/v3/truerater.com/messages');
    curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_POST, 1);
    $post = array(
        'from' =>  $mailfromname .'<'.$mailfrom.'>',
        'to' => $toname.'<'.$to.'>',
        'cc' => '',
        'bcc' => '',
        'subject' => $subject,
        'html'=>$html,
        'text'=>$text,
        'o:tracking'=>'yes',
        'o:tracking-clicks'=>'yes',
        'o:tracking-opens'=>'yes',
        'o:tag'=>$tag,
        'h:Reply-To'=>$replyto,
    );
    if(sizeOf($attachment) > 0){
        $i=0;
        foreach ($attachment as $attach){
            $attachPath = substr($attach, strrpos($attach, '/public/') + 1);
            $post['attachment['.$i.']'] = curl_file_create($attach, '', substr($attachPath, strrpos($attachPath, '/') + 1));
            $i=$i+1;
        }
    }
    $headers_arr = array("Content-Type:multipart/form-data");
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    curl_setopt($ch, CURLOPT_USERPWD, 'api' . ':' . $key);
    curl_setopt($ch, CURLOPT_HEADER, $headers_arr);
    curl_setopt($ch, CURLOPT_ENCODING, 'UTF-8');
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    
    $result = curl_exec($ch);
    
    
    if (curl_errno($ch)) {
        $result = curl_error($ch);
        \Log::info($result);
    }
    else{
        $result = json_decode($result,true);
    }
    curl_close($ch);
   
    \Log::info($result);
    return $result;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接