App Engine Python SDK version 1.8.1
[gae.git] / python / php / sdk / google / appengine / api / mail / BaseMessage.php
blobed0a18e01d9dbfaebebf1add4a55789a5cc568a9
1 <?php
2 /**
3 * Copyright 2007 Google Inc.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 /**
20 namespace google\appengine\api\mail;
22 require_once 'google/appengine/api/mail_service_pb.php';
23 require_once 'google/appengine/runtime/ApiProxy.php';
24 require_once 'google/appengine/runtime/ApplicationError.php';
26 use google\appengine\MailAttachment;
27 use google\appengine\MailHeader;
28 use google\appengine\MailMessage;
29 use google\appengine\MailServiceError\ErrorCode;
31 /**
32 * Abstract base class for sending mail using the App Engine mail APIs.
34 abstract class BaseMessage {
35 // Force AdminMessage and Message to implement send.
36 abstract public function send();
39 * Force AdminMessage and Message to implment getFunctionArray, required
40 * for parsing the options array.
42 abstract protected function getFunctionArray();
44 // Container for the MailMessage protobuf.
45 protected $message = null;
47 // Whitelisted headers.
48 protected static $allowed_headers = array(
49 'auto-submitted', 'in-reply-to', 'list-id', 'list-unsubscribe',
50 'on-behalf-of', 'references', 'resent-date', 'resent-from', 'resent-to');
52 // Blacklisted extension types.
53 protected static $extension_blacklist = array(
54 'ade', 'adp', 'bat', 'chm', 'cmd', 'com', 'cpl', 'exe', 'hta', 'ins',
55 'isp', 'jse', 'lib', 'mde', 'msc', 'msp', 'mst', 'pif', 'scr', 'sct',
56 'shb', 'sys', 'vb', 'vbe', 'vbs', 'vxd', 'wsc', 'wsf', 'wsh');
58 // Setter functions for constructor.
59 protected static $set_functions = array('sender' => 'setSender',
60 'replyto' => 'setReplyTo',
61 'to' => 'addTo',
62 'cc' => 'addCc',
63 'bcc' => 'addBcc',
64 'subject' => 'setSubject',
65 'textBody' => 'setTextBody',
66 'htmlBody' => 'setHtmlBody',
67 'header' => 'addHeaderArray',
68 'attachment' => 'addAttachmentArray');
70 /**
71 * Construct an instance of Message.
73 * @param array $options Options for message content, key as per set_functions
74 * shown above, value to be set.
75 * @throws \InvalidArgumentException If the options variable passed was not an
76 * array, if an invalid option was set in the options array, or if a value
77 * to be set by the options array was invalid.
79 public function __construct($options = null) {
80 $this->message = new MailMessage();
82 if (isset($options)) {
83 if (is_array($options)) {
84 foreach($options as $key => $value) {
85 // If this is a valid option to set.
86 $allowed_functions = $this->getFunctionArray();
87 if (array_key_exists($key, $allowed_functions)) {
88 // Call the corresponding setter function with the input argument.
89 $func_name = $allowed_functions[$key];
90 call_user_func(array($this, $func_name), $value);
91 } else {
92 $error = sprintf("Message received an invalid option: %s", $key);
93 throw new \InvalidArgumentException($error);
96 } else {
97 $error = sprintf("Message expects an array, not %s", gettype($options));
98 throw new \InvalidArgumentException($error);
104 * Adds an attachment to the Message object.
106 * @param string $filename Filename of the attachment.
107 * @param mixed $data File data of the attachment.
108 * @throws \InvalidArgumentException If the input is not an array or if the
109 * attachment type is invalid (i.e. the filename is not a string, or the
110 * file extension is blacklisted).
112 public function addAttachment($filename, $data) {
113 $this->addAttachmentArray(array($filename => $data));
117 * Adds an array of attachments to the Message object.
119 * @param array Attachments as filename => data pairs.
120 * Example: array("filename.txt" => "This is the file contents.");
121 * @throws \InvalidArgumentException If the input is not an array or if the
122 * attachment type is invalid (i.e. the filename is not a string, or the
123 * file extension is blacklisted).
125 public function addAttachmentArray($attach_array) {
126 if (!is_array($attach_array)) {
127 $error = sprintf("Input is not an array (Actual type: %s).",
128 gettype($attach_array));
129 throw new \InvalidArgumentException($error);
132 $error = "";
133 foreach($attach_array as $filename => $data) {
134 if (!$this->checkValidAttachment($filename, $error)) {
135 throw new \InvalidArgumentException($error);
139 foreach($attach_array as $filename => $data) {
140 $new_attachment = $this->message->addAttachment();
141 $new_attachment->setFilename($filename);
142 $new_attachment->setData($data);
147 * Adds a header pair to the mail object.
149 * @param string $key Header name (from the whitelist) to be added.
150 * @param string $value Header value to be added.
151 * @throws \InvalidArgumentException If the header is not on the whitelist, or
152 * if the header is invalid (i.e. not a string).
154 public function addHeader($key, $value) {
155 if (!is_string($key)) {
156 $error = sprintf("Header key is not a string (Actual type: %s).",
157 gettype($key));
158 throw new \InvalidArgumentException($error);
160 $this->addHeaderArray(array($key => $value));
164 * Adds an array of headers to the mail object.
166 * @param array An array of headers.
167 * @throws \InvalidArgumentException If the input is not an array, or if
168 * headers are not on the whitelist, or if a header is invalid
169 * (i.e. not a string).
171 public function addHeaderArray($header_array) {
172 if (!is_array($header_array)) {
173 $error = sprintf("Input is not an array (Actual type: %s).",
174 gettype($header_array));
175 throw new \InvalidArgumentException($error);
178 $error = "";
179 foreach($header_array as $key => $value) {
180 if (!$this->checkValidHeader($key, $value, $error)) {
181 throw new \InvalidArgumentException($error);
185 foreach($header_array as $key => $value) {
186 $new_header = $this->message->addHeader();
187 $new_header->setName($key);
188 $new_header->setValue($value);
193 * Checks that an attachment is valid.
195 * @param string $filename Filename of the attachment.
196 * @return bool True if successful, false otherwise.
197 * @param string &$error Error message to be set if the header is invalid.
199 protected function checkValidAttachment($filename, &$error) {
200 if (!is_string($filename)) {
201 $error = sprintf("Filename must be a string but was type %s",
202 gettype($filename));
203 return false;
206 $path_parts = pathinfo($filename);
207 if (isset($path_parts['extension'])) {
208 if (in_array($path_parts['extension'], self::$extension_blacklist)) {
209 $error = sprintf("'%s' is a blacklisted file extension.",
210 $path_parts['extension']);
211 return false;
215 return true;
219 * Checks that an email is valid.
221 * @param string $email The email to be validated.
222 * @return bool True if valid, false otherwise.
224 protected function checkValidEmail($email) {
225 if (filter_var($email, FILTER_VALIDATE_EMAIL) !== false) {
226 return true;
228 return false;
232 * Check validity of a header pair.
234 * @param string $key Header key.
235 * @param string $value Header value.
236 * @param string &$error Error message to be set if the header is invalid.
237 * @return bool True if successful, false otherwise.
239 protected function checkValidHeader($key, $value, &$error) {
240 if (!is_string($key)) {
241 $error = sprintf("Header key is not a string (Actual type: %s).",
242 gettype($key));
243 return false;
244 } else if (!in_array(strtolower($key), self::$allowed_headers)) {
245 // Array keys don't have consistent case.
246 $error = sprintf("Input header '%s: %s' is not whitelisted for use with" .
247 " the Google App Engine Mail Service.", $key, $value);
248 return false;
250 return true;
254 * Clear all attachments from the mail object.
256 public function clearAttachments() {
257 $this->message->clearAttachment();
261 * Clear all headers from the mail object.
263 public function clearHeaders() {
264 $this->message->clearHeader();
268 * Handles application errors generated by the RPC call.
270 * @param ApplicationError An exception caught during the RPC call.
271 * @throws \RuntimeException If there was an internal error or bad request.
272 * @throws \InvalidArgumentException If there was an unauthorized sender,
273 * an invalid attachment type, or an invalid header name.
274 * @throws ApplicationError If the error is not one of the above.
276 protected function handleApplicationError($e) {
277 switch($e->getApplicationError()) {
278 case ErrorCode::INTERNAL_ERROR:
279 case ErrorCode::BAD_REQUEST:
280 throw new \RuntimeException(
281 "Mail Service Error: " . $e->getMessage());
282 case ErrorCode::UNAUTHORIZED_SENDER:
283 $error = sprintf("Mail Service Error: Sender (%s) is not an " .
284 "authorized email address.",
285 $this->message->getSender());
286 throw new \InvalidArgumentException($error);
287 case ErrorCode::INVALID_ATTACHMENT_TYPE:
288 throw new \InvalidArgumentException(
289 "Mail Service Error: Invalid attachment type.");
290 case ErrorCode::INVALID_HEADER_NAME:
291 throw new \InvalidArgumentException(
292 "Mail Service Error: Invalid header name.");
293 default:
294 throw $e;
299 * Sets HTML content for the email body.
301 * @param string $text HTML to add.
302 * @throws \InvalidArgumentException If text is not a string.
304 public function setHtmlBody($text) {
305 if (!is_string($text)) {
306 $error = sprintf("HTML text given is not a string (Actual type: %s).",
307 gettype($text));
308 throw new \InvalidArgumentException($error);
310 $this->message->setHtmlbody($text);
314 * Sets a reply-to address for the mail object.
316 * @param string $email Reply-to address.
317 * @throws \InvalidArgumentException If the input reply-to address is an
318 * invalid email address.
320 public function setReplyTo($email) {
321 if (!$this->checkValidEmail($email)) {
322 throw new \InvalidArgumentException("Invalid reply-to: ". $email);
324 $this->message->setReplyto($email);
328 * Sets the sender for the mail object.
330 * @param string $email Email of the sender.
331 * @throws \InvalidArgumentException If the input sender is an invalid email
332 * address.
334 public function setSender($email) {
335 if (!$this->checkValidEmail($email)) {
336 throw new \InvalidArgumentException("Invalid sender: ". $email);
338 $this->message->setSender($email);
342 * Sets the subject for the mail object.
344 * @param string $subject Subject line.
345 * @throws \InvalidArgumentException If subject line is not a string.
347 public function setSubject($subject) {
348 if (!is_string($subject)) {
349 $error = sprintf("Subject given is not a string (Actual type: %s).",
350 gettype($subject));
351 throw new \InvalidArgumentException($error);
353 $this->message->setSubject($subject);
357 * Sets plain text for the email body.
359 * @param string $text Plain text to add.
360 * @return bool True if successful, false otherwise.
361 * @throws \InvalidArgumentException If text is not a string.
363 public function setTextBody($text) {
364 if (!is_string($text)) {
365 $error = sprintf("Plain text given is not a string (Actual type: %s).",
366 gettype($text));
367 throw new \InvalidArgumentException($error);
369 $this->message->setTextbody($text);