Laravel-exchange EWS邮件服务
Laravel-exchange EWS服务库
PHP Exchange Web Services
PHP Exchange Web服务库(PHP-ews)旨在使用Exchange Web服务简化与Microsoft Exchange服务器的通信。它处理使用SOAP服务所需的NTLM身份验证,并为形成请求所需的复杂类型提供面向对象的接口。
github:https://github.com/jamesiarmes/php-ews
Dependencies(依赖)
- Composer
- PHP 5.4 or greater
- Exchange 2007 or later
- php extension=soap open
Installation(安装)
$ composer require php-ews/php-ews "~1.0"
Usage(使用)
.env
EWS_HOST=mail.test.com.cn EWS_USERNAME=test@test.com.cn EWS_PASSWORD='你的密码'
创建EWS类
App\Libs\EWS.php
<?php namespace App\Libs; use jamesiarmes\PhpEws\Client; use App\Exceptions\EWSException; use jamesiarmes\PhpEws\Type\BodyType; use jamesiarmes\PhpEws\Type\ItemIdType; use jamesiarmes\PhpEws\Type\MessageType; use jamesiarmes\PhpEws\Request\SendItemType; use jamesiarmes\PhpEws\Type\EmailAddressType; use jamesiarmes\PhpEws\Request\CreateItemType; use jamesiarmes\PhpEws\Type\TargetFolderIdType; use jamesiarmes\PhpEws\Type\FileAttachmentType; use jamesiarmes\PhpEws\Enumeration\BodyTypeType; use jamesiarmes\PhpEws\Type\SingleRecipientType; use jamesiarmes\PhpEws\Request\CreateAttachmentType; use jamesiarmes\PhpEws\Enumeration\ResponseClassType; use jamesiarmes\PhpEws\Type\DistinguishedFolderIdType; use jamesiarmes\PhpEws\ArrayType\ArrayOfRecipientsType; use jamesiarmes\PhpEws\Enumeration\MessageDispositionType; use jamesiarmes\PhpEws\ArrayType\NonEmptyArrayOfAllItemsType; use jamesiarmes\PhpEws\ArrayType\NonEmptyArrayOfAttachmentsType; use jamesiarmes\PhpEws\ArrayType\NonEmptyArrayOfBaseItemIdsType; use jamesiarmes\PhpEws\Enumeration\DistinguishedFolderIdNameType; class EWS { /** * [EWS client] * * @var [Object] */ public $client; /** * [邮箱地址] * * @var [String] */ public $emails; /** * [邮件标题] * * @var [String] */ public $subject; /** * [邮件内容] * * @var [String] */ public $body; /** * [附件的绝对路径] * * @var [String] */ public $attachment; /** * [构造方法] * * @return [Object] */ public function __construct() { $host = env('EWS_HOST', null); $username = env('EWS_USERNAME', null); $password = env('EWS_PASSWORD', null); $version = Client::VERSION_2016; $this->client = new Client($host, $username, $password, $version); } /** * 发送邮件 * * @param [Array] $data [数据] * * @return [Json] [结果] */ public function send($data) { if(empty($data['emails'])){ throw new EWSException('The email is invalid.', 422); } if(!empty($data['attachments'])){ foreach ($data['attachments'] as $path) { if(!file_exists($path)){ throw new EWSException("The file:{$path} is not exists.", 404); } } } //初始化 $this->emails = $data['emails'] ?? ''; $this->subject = $data['subject'] ?? ''; $this->body = $data['body'] ?? ''; $this->attachments = $data['attachments'] ?? ''; //创建所需要参数 $message = $this->createMessage(); $request = $this->createRequest($message); //创建草稿并返回 $item = $this->createItem($request); $send = $this->doSend($item); return $send; } /** * [创建草稿并且返回] * * @param [Request] $request [message] * * @return [Array] [返回创建信息] */ protected function createItem($request) { $response = $this->client->CreateItem($request); //分析结果 $response_messages = $response->ResponseMessages->CreateItemResponseMessage; $data = []; foreach ($response_messages as $response_message) { // Make sure the request succeeded. if ($response_message->ResponseClass != ResponseClassType::SUCCESS) { throw new EWSException($response_message->MessageText, $response_message->ResponseCode); } // Iterate over the created messages, printing the id for each. foreach ($response_message->Items->Message as $item) { $data['code'] = 0; $data['item_id'] = $item->ItemId->Id; $data['change_key'] = $item->ItemId->ChangeKey; } } return $data; } /** * [执行发送] * * @param [Array] $item [草稿] * * @return [Array] [结果] */ protected function doSend($item) { //判断是否有附件添加 if(!empty($this->attachments) && $item['code'] == 0){ $item = $this->addAttachment($item); } $message_id = $item['item_id']; $change_key = $item['change_key']; // Build the request. $request = new SendItemType(); $request->SaveItemToFolder = true; $request->ItemIds = new NonEmptyArrayOfBaseItemIdsType(); // Add the message to the request. $item = new ItemIdType(); $item->Id = $message_id; $item->ChangeKey = $change_key; $request->ItemIds->ItemId[] = $item; // Configure the folder to save the sent message to. $send_folder = new TargetFolderIdType(); $send_folder->DistinguishedFolderId = new DistinguishedFolderIdType(); $send_folder->DistinguishedFolderId->Id = DistinguishedFolderIdNameType::SENT; $request->SavedItemFolderId = $send_folder; $response = $this->client->SendItem($request); // Iterate over the results, printing any error messages. $response_messages = $response->ResponseMessages->SendItemResponseMessage; $data = []; foreach ($response_messages as $response_message) { // Make sure the request succeeded. if ($response_message->ResponseClass != ResponseClassType::SUCCESS) { throw new EWSException($response_message->MessageText, $response_message->ResponseCode); } $data['code'] = 0; $data['message'] = 'Message sent successfully.'; } return $data; } /** * [添加附件] * * @param [Item] $item [草稿] * * @return [Array] [附件结果] */ protected function addAttachment($item) { // Build the request, $request = new CreateAttachmentType(); $request->ParentItemId = new ItemIdType(); $request->ParentItemId->Id = $item['item_id']; $request->Attachments = new NonEmptyArrayOfAttachmentsType(); // Build the file attachment. foreach ($this->attachments as $path) { // Open file handlers. $file = new \SplFileObject($path); $finfo = finfo_open(); $attachment = new FileAttachmentType(); $attachment->Content = $file->openFile()->fread($file->getSize()); $attachment->Name = $file->getBasename(); $attachment->ContentType = finfo_file($finfo, $path); $request->Attachments->FileAttachment[] = $attachment; } $response = $this->client->CreateAttachment($request); $response_messages = $response->ResponseMessages->CreateAttachmentResponseMessage; $item = []; foreach ($response_messages as $response_message) { // Make sure the request succeeded. if ($response_message->ResponseClass != ResponseClassType::SUCCESS) { throw new EWSException($response_message->MessageText, $response_message->ResponseCode); } // Iterate over the created attachments, printing the id of each. foreach ($response_message->Attachments->FileAttachment as $attachment) { $item['code'] = 0; $item['item_id'] = $attachment->AttachmentId->RootItemId; $item['change_key'] = $attachment->AttachmentId->RootItemChangeKey; $item['attachment_id'] = $attachment->AttachmentId->Id; } } return $item; } /** * 创建草稿箱 * * @param [Message] $message [要发送的文本信息] * * @return [request] [] */ protected function createRequest($message) { // Build the request, $request = new CreateItemType(); $request->Items = new NonEmptyArrayOfAllItemsType(); // Add the message to the request. $request->Items->Message[] = $message; // Save the message, but do not send it. $request->MessageDisposition = MessageDispositionType::SAVE_ONLY; return $request; } /** * 创建 发件人 标题 内容 * * @param [Client] $client [EWS客户端] * @param [EmailAddress] $email [邮箱地址] * @param [Subject] $subject [标题] * @param [Body] $body [内容] * * @return [Message] [message] */ protected function createMessage() { // Create the message. $message = new MessageType(); $message->Subject = $this->subject; $message->ToRecipients = new ArrayOfRecipientsType(); // Set the sender. $message->From = new SingleRecipientType(); $message->From->Mailbox = new EmailAddressType(); $message->From->Mailbox->EmailAddress = env('EWS_USERNAME', null); foreach ($this->emails as $key => $email) { // Set the recipient. $to = $email['to'] ?? ''; $name = $email['name'] ?? $to; $recipient = new EmailAddressType(); $recipient->Name = $name; $recipient->EmailAddress = $to; $message->ToRecipients->Mailbox[] = $recipient; } // Set the message body. $message->Body = new BodyType(); $message->Body->BodyType = BodyTypeType::HTML; $message->Body->_ = $this->body; return $message; } }
发送邮件:
App\Controllers\MailController.php
<?php namespace App\Http\Controllers; use App\Libs\EWS; use Illuminate\Http\Request; class MailController extends Controller { public function seed(Request $request) { //要发送给的人的姓名和邮箱地址 $emails = [ [ 'to' => 'test1@test.com', 'name' => '张三' ], [ 'to' => 'test2@test.com', 'name' => '李四' ] ]; //附件路径 $attachments = [ storage_path('1.pdf'), storage_path('2.pdf') ]; //发送 $exchange = new EWS(); $send = $exchange->send([ 'emails' => $emails, 'subject' => 'test', 'body' => response(view('emails.pdf', ['name' => '邮箱测试']))->getContent(), //这里可以使用blade模板自定义你的模板样式 'attachments' => $attachments ]); return response()->json($send); } }
自定义异常
App\Exceptions\EWSException.php
<?php namespace App\Exceptions; use Exception; class EWSException extends Exception { }
自定义异常处理
App\Exceptions\Handler.php
<?php namespace App\Exceptions; use Exception; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; class Handler extends ExceptionHandler { /** * A list of the exception types that are not reported. * * @var array */ protected $dontReport = [ // ]; /** * A list of the inputs that are never flashed for validation exceptions. * * @var array */ protected $dontFlash = [ 'password', 'password_confirmation', ]; /** * Report or log an exception. * * This is a great spot to send exceptions to Sentry, Bugsnag, etc. * * @param \Exception $exception * @return void */ public function report(Exception $exception) { if ($exception instanceof EWSException) { //如果是邮件发送异常,这里做一些记录 } parent::report($exception); } /** * Render an exception into an HTTP response. * * @param \Illuminate\Http\Request $request * @param \Exception $exception * @return \Illuminate\Http\Response */ public function render($request, Exception $exception) { if($exception instanceof EWSException) { $result = [ "code" => $exception->getCode(), "message" => $exception->getMessage() ]; return response()->json($result, $exception->getCode()); } return parent::render($request, $exception); } }