Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • Message
  • MimePart
  • SendmailMailer
  • SmtpMailer

Interfaces

  • IMailer

Exceptions

  • SmtpException
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  */
 11: 
 12: namespace Nette\Mail;
 13: 
 14: use Nette,
 15:     Nette\Utils\Strings;
 16: 
 17: 
 18: /**
 19:  * MIME message part.
 20:  *
 21:  * @author     David Grudl
 22:  *
 23:  * @property-read array $headers
 24:  * @property-write $contentType
 25:  * @property   string $encoding
 26:  * @property   mixed $body
 27:  */
 28: class MimePart extends Nette\Object
 29: {
 30:     /** encoding */
 31:     const ENCODING_BASE64 = 'base64',
 32:         ENCODING_7BIT = '7bit',
 33:         ENCODING_8BIT = '8bit',
 34:         ENCODING_QUOTED_PRINTABLE = 'quoted-printable';
 35: 
 36:     /** @internal */
 37:     const EOL = "\r\n";
 38:     const LINE_LENGTH = 76;
 39: 
 40:     /** @var array */
 41:     private $headers = array();
 42: 
 43:     /** @var array */
 44:     private $parts = array();
 45: 
 46:     /** @var string */
 47:     private $body;
 48: 
 49: 
 50:     /**
 51:      * Sets a header.
 52:      * @param  string
 53:      * @param  string|array  value or pair email => name
 54:      * @param  bool
 55:      * @return self
 56:      */
 57:     public function setHeader($name, $value, $append = FALSE)
 58:     {
 59:         if (!$name || preg_match('#[^a-z0-9-]#i', $name)) {
 60:             throw new Nette\InvalidArgumentException("Header name must be non-empty alphanumeric string, '$name' given.");
 61:         }
 62: 
 63:         if ($value == NULL) { // intentionally ==
 64:             if (!$append) {
 65:                 unset($this->headers[$name]);
 66:             }
 67: 
 68:         } elseif (is_array($value)) { // email
 69:             $tmp = & $this->headers[$name];
 70:             if (!$append || !is_array($tmp)) {
 71:                 $tmp = array();
 72:             }
 73: 
 74:             foreach ($value as $email => $recipient) {
 75:                 if ($recipient !== NULL && !Strings::checkEncoding($recipient)) {
 76:                     Nette\Utils\Validators::assert($recipient, 'unicode', "header '$name'");
 77:                 }
 78:                 if (preg_match('#[\r\n]#', $recipient)) {
 79:                     throw new Nette\InvalidArgumentException("Name must not contain line separator.");
 80:                 }
 81:                 Nette\Utils\Validators::assert($email, 'email', "header '$name'");
 82:                 $tmp[$email] = $recipient;
 83:             }
 84: 
 85:         } else {
 86:             $value = (string) $value;
 87:             if (!Strings::checkEncoding($value)) {
 88:                 throw new Nette\InvalidArgumentException("Header is not valid UTF-8 string.");
 89:             }
 90:             $this->headers[$name] = preg_replace('#[\r\n]+#', ' ', $value);
 91:         }
 92:         return $this;
 93:     }
 94: 
 95: 
 96:     /**
 97:      * Returns a header.
 98:      * @param  string
 99:      * @return mixed
100:      */
101:     public function getHeader($name)
102:     {
103:         return isset($this->headers[$name]) ? $this->headers[$name] : NULL;
104:     }
105: 
106: 
107:     /**
108:      * Removes a header.
109:      * @param  string
110:      * @return self
111:      */
112:     public function clearHeader($name)
113:     {
114:         unset($this->headers[$name]);
115:         return $this;
116:     }
117: 
118: 
119:     /**
120:      * Returns an encoded header.
121:      * @param  string
122:      * @param  string
123:      * @return string
124:      */
125:     public function getEncodedHeader($name)
126:     {
127:         $offset = strlen($name) + 2; // colon + space
128: 
129:         if (!isset($this->headers[$name])) {
130:             return NULL;
131: 
132:         } elseif (is_array($this->headers[$name])) {
133:             $s = '';
134:             foreach ($this->headers[$name] as $email => $name) {
135:                 if ($name != NULL) { // intentionally ==
136:                     $s .= self::encodeHeader($name, $offset, strpbrk($name, '.,;<@>()[]"=?'));
137:                     $email = " <$email>";
138:                 }
139:                 $email .= ',';
140:                 if ($s !== '' && $offset + strlen($email) > self::LINE_LENGTH) {
141:                     $s .= self::EOL . "\t";
142:                     $offset = 1;
143:                 }
144:                 $s .= $email;
145:                 $offset += strlen($email);
146:             }
147:             return substr($s, 0, -1); // last comma
148: 
149:         } elseif (preg_match('#^(\S+; (?:file)?name=)"(.*)"\z#', $this->headers[$name], $m)) { // Content-Disposition
150:             $offset += strlen($m[1]);
151:             return $m[1] . '"' . self::encodeHeader($m[2], $offset) . '"';
152: 
153:         } else {
154:             return self::encodeHeader($this->headers[$name], $offset);
155:         }
156:     }
157: 
158: 
159:     /**
160:      * Returns all headers.
161:      * @return array
162:      */
163:     public function getHeaders()
164:     {
165:         return $this->headers;
166:     }
167: 
168: 
169:     /**
170:      * Sets Content-Type header.
171:      * @param  string
172:      * @param  string
173:      * @return self
174:      */
175:     public function setContentType($contentType, $charset = NULL)
176:     {
177:         $this->setHeader('Content-Type', $contentType . ($charset ? "; charset=$charset" : ''));
178:         return $this;
179:     }
180: 
181: 
182:     /**
183:      * Sets Content-Transfer-Encoding header.
184:      * @param  string
185:      * @return self
186:      */
187:     public function setEncoding($encoding)
188:     {
189:         $this->setHeader('Content-Transfer-Encoding', $encoding);
190:         return $this;
191:     }
192: 
193: 
194:     /**
195:      * Returns Content-Transfer-Encoding header.
196:      * @return string
197:      */
198:     public function getEncoding()
199:     {
200:         return $this->getHeader('Content-Transfer-Encoding');
201:     }
202: 
203: 
204:     /**
205:      * Adds or creates new multipart.
206:      * @return MimePart
207:      */
208:     public function addPart(MimePart $part = NULL)
209:     {
210:         return $this->parts[] = $part === NULL ? new self : $part;
211:     }
212: 
213: 
214:     /**
215:      * Sets textual body.
216:      * @return self
217:      */
218:     public function setBody($body)
219:     {
220:         $this->body = $body;
221:         return $this;
222:     }
223: 
224: 
225:     /**
226:      * Gets textual body.
227:      * @return mixed
228:      */
229:     public function getBody()
230:     {
231:         return $this->body;
232:     }
233: 
234: 
235:     /********************* building ****************d*g**/
236: 
237: 
238:     /**
239:      * Returns encoded message.
240:      * @return string
241:      */
242:     public function generateMessage()
243:     {
244:         $output = '';
245:         $boundary = '--------' . Strings::random();
246: 
247:         foreach ($this->headers as $name => $value) {
248:             $output .= $name . ': ' . $this->getEncodedHeader($name);
249:             if ($this->parts && $name === 'Content-Type') {
250:                 $output .= ';' . self::EOL . "\tboundary=\"$boundary\"";
251:             }
252:             $output .= self::EOL;
253:         }
254:         $output .= self::EOL;
255: 
256:         $body = (string) $this->body;
257:         if ($body !== '') {
258:             switch ($this->getEncoding()) {
259:                 case self::ENCODING_QUOTED_PRINTABLE:
260:                     $output .= function_exists('quoted_printable_encode') ? quoted_printable_encode($body) : self::encodeQuotedPrintable($body);
261:                     break;
262: 
263:                 case self::ENCODING_BASE64:
264:                     $output .= rtrim(chunk_split(base64_encode($body), self::LINE_LENGTH, self::EOL));
265:                     break;
266: 
267:                 case self::ENCODING_7BIT:
268:                     $body = preg_replace('#[\x80-\xFF]+#', '', $body);
269:                     // break intentionally omitted
270: 
271:                 case self::ENCODING_8BIT:
272:                     $body = str_replace(array("\x00", "\r"), '', $body);
273:                     $body = str_replace("\n", self::EOL, $body);
274:                     $output .= $body;
275:                     break;
276: 
277:                 default:
278:                     throw new Nette\InvalidStateException('Unknown encoding.');
279:             }
280:         }
281: 
282:         if ($this->parts) {
283:             if (substr($output, -strlen(self::EOL)) !== self::EOL) {
284:                 $output .= self::EOL;
285:             }
286:             foreach ($this->parts as $part) {
287:                 $output .= '--' . $boundary . self::EOL . $part->generateMessage() . self::EOL;
288:             }
289:             $output .= '--' . $boundary.'--';
290:         }
291: 
292:         return $output;
293:     }
294: 
295: 
296:     /********************* QuotedPrintable helpers ****************d*g**/
297: 
298: 
299:     /**
300:      * Converts a 8 bit header to a string.
301:      * @param  string
302:      * @param  int
303:      * @param  bool
304:      * @return string
305:      */
306:     private static function encodeHeader($s, & $offset = 0, $force = FALSE)
307:     {
308:         $o = '';
309:         if ($offset >= 55) { // maximum for iconv_mime_encode
310:             $o = self::EOL . "\t";
311:             $offset = 1;
312:         }
313: 
314:         if (!$force && strspn($s, "!\"#$%&\'()*+,-./0123456789:;<>@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^`abcdefghijklmnopqrstuvwxyz{|}=? _\r\n\t") === strlen($s)
315:             && ($offset + strlen($s) <= self::LINE_LENGTH)
316:         ) {
317:             $offset += strlen($s);
318:             return $o . $s;
319:         }
320: 
321:         $o .= str_replace("\n ", "\n\t", substr(iconv_mime_encode(str_repeat(' ', $offset), $s, array(
322:             'scheme' => 'B', // Q is broken
323:             'input-charset' => 'UTF-8',
324:             'output-charset' => 'UTF-8',
325:         )), $offset + 2));
326: 
327:         $offset = strlen($o) - strrpos($o, "\n");
328:         return $o;
329:     }
330: 
331: 
332:     /**
333:      * Converts a 8 bit string to a quoted-printable string.
334:      * @param  string
335:      * @return string
336:      */}
337: 
Nette Framework 2.0.11 API API documentation generated by ApiGen 2.8.0