21 parent::edit_form($form, $form_state);
22 global $cookie_domain;
24 $form[
'connection'][
'settings'][
'box_type'] = array(
26 '#title' => t(
'Protocol'),
27 '#options' => array(
'imap' =>
'IMAP',
'pop3' =>
'POP3',
'local' =>
'Local mbox file'),
28 '#default_value' => $this->
get_setting(
'box_type',
'imap'),
29 '#description' => t(
'You can use the IMAP/POP3 protocols, or retrieve from an mbox file on the local file system.'),
32 $ajax_settings = array(
33 'callback' =>
'_mailinglist_mailbox_test',
34 'wrapper' =>
'mailinglist_test_results',
38 'message' => t(
'Please wait - testing connection settings...'),
41 $form[
'connection'][
'settings'][
'folder'] = array(
42 '#type' =>
'textfield',
43 '#title' => t(
'Folder'),
45 '#description' => t(
'The folder where the mail is stored. If you want this mailbox to read from a local mbox file, give the path relative to the Drupal installation directory.'),
46 '#ajax' => $ajax_settings,
49 $form[
'connection'][
'settings'][
'domain'] = array(
50 '#type' =>
'textfield',
51 '#title' => t(
'Domain'),
53 '#description' => t(
'The domain of the server used to collect mail.'),
54 '#ajax' => $ajax_settings,
57 $form[
'connection'][
'settings'][
'port'] = array(
58 '#type' =>
'textfield',
59 '#title' => t(
'Port'),
63 '#description' => t(
'The mailbox port number (usually 110 for POP3, 143 for IMAP).'),
64 '#element_validate' => array(
'element_validate_integer_positive'),
65 '#ajax' => $ajax_settings,
68 $form[
'connection'][
'settings'][
'name'] = array(
69 '#type' =>
'textfield',
70 '#title' => t(
'Username'),
72 '#description' => t(
'This username is used while logging into this mailbox during mail retrieval.'),
73 '#ajax' => $ajax_settings,
75 $form[
'connection'][
'settings'][
'pass'] = array(
76 '#type' =>
'textfield',
77 '#title' => t(
'Password'),
79 '#description' => t(
'The mailbox password corresponding to the username above. Consider using a non-vital password, since this field is stored with minimal encryption in the database and displayed here.'),
80 '#ajax' => $ajax_settings,
83 $form[
'connection'][
'settings'][
'extraimap'] = array(
84 '#type' =>
'textfield',
85 '#title' => t(
'Extra commands'),
86 '#default_value' => $this->
get_setting(
'extraimap'),
87 '#description' => t(
'In some circumstances you need to issue extra commands to connect to your mail server (for example "/notls", "/novalidate-cert" etc.). See documentation for <a href="@imap-open">imap_open</a>.', array(
'@imap-open' => url(
'http://php.net/imap_open'))),
88 '#ajax' => $ajax_settings,
90 $form[
'connection'][
'settings'][
'results'] = array(
91 '#type' =>
'container',
92 '#attributes' => array(
93 'id' =>
'mailinglist_test_results',
97 $form[
'extra'][
'settings'][
'flag_after_read'] = array(
98 '#type' =>
'checkbox',
99 '#title' => t(
'Mark messages as seen/read after they are processed?'),
100 '#default_value' => $this->
get_setting(
'flag_after_read', TRUE),
101 '#description' => t(
'Note that messages cannot be marked as seen/read for POP3 accounts.'),
103 $form[
'extra'][
'settings'][
'delete_after_read'] = array(
104 '#type' =>
'checkbox',
105 '#title' => t(
'Delete messages after they are processed?'),
106 '#default_value' => $this->
get_setting(
'delete_after_read', TRUE),
107 '#description' => t(
'Uncheck this box to leave read messages in the mailbox. They will not be processed again unless they become marked as unread. If you selected "POP3" as your mailbox type, you must check this box.'),
116 parent::edit_form_validate($form, $form_state);
120 if ($form_state[
'values'][
'settings'][
'box_type'] ==
'pop3' && $form_state[
'values'][
'settings'][
'delete_after_read'] == 0) {
121 drupal_set_message(t(
'Unless you check off "Delete messages after they are processed" when using a POP3 mailbox, old emails will be re-imported each time the mailbox is processed. You can partially prevent this by mapping Message ID to a unique target in the processor configuration - see INSTALL.txt or advanced help for more information'),
'warning');
123 if (($form_state[
'values'][
'settings'][
'box_type'] ==
'pop3' && $form_state[
'values'][
'settings'][
'port'] != 110) || ($form_state[
'values'][
'settings'][
'box_type'] ==
'imap' && $form_state[
'values'][
'settings'][
'port'] != 143)) {
124 drupal_set_message(t(
'Non-standard Port:') .
' ' . $form_state[
'values'][
'settings'][
'port'] .
' (' . $form_state[
'values'][
'settings'][
'box_type'] .
')',
'warning');
132 parent::edit_form_submit($form, $form_state);
148 dpm($this->settings);
149 extract($this->settings);
167 extract($this->settings);
174 throw new Exception(t(
'Unable to connect to %mail. Please check the <a href="@mailbox-edit">connection settings</a> for this mailbox.', array(
'%mail' => $this->mail,
'@mailbox-edit' => url(
'admin/structure/mailinglist/list/' . $this->mail .
'/edit'))));
178 while ($new && (!$limit || $retrieved < $limit)) {
181 $messages[] = $message;
185 watchdog(
'mailinglist',
'Mailbox %mail was checked and contained %retrieved messages.', array(
'%mail' => $this->admin_title,
'%retrieved' => $retrieved), WATCHDOG_INFO);
197 extract($this->settings);
200 $is_local = ($type ==
'local');
201 $folder_is_set = (!empty($folder) && $folder !=
'INBOX');
202 $connect_is_set = !empty($domain) && !empty($port) && !empty($name) && !empty($pass);
204 if (($is_local && $folder_is_set) || (!$is_local && $connect_is_set)) {
207 $ret[] = array(
'severity' =>
'status',
'message' => t(
'Mailinglist was able to connect to the mailbox.'));
209 $status = imap_status($result, $box, SA_MESSAGES);
211 $ret[] = array(
'severity' =>
'status',
'message' => t(
'There are @messages messages in the mailbox folder.', array(
'@messages' => $status->messages)));
214 $ret[] = array(
'severity' =>
'warning',
'message' => t(
'Mailinglist could not open the specified folder'));
220 $ret[] = array(
'severity' =>
'error',
'message' => t(
'Mailinglist could not access the mailbox using these settings'));
229 $this->
log(
"Purge Message: " . $message);
230 if (isset($message[
'imap_uid'])) {
233 if ($this->settings[
'delete_after_read']) {
234 imap_delete($result, $message[
'imap_uid'], FT_UID);
236 elseif (!isset($this->settings[
'flag_after_read']) || ($this->settings[
'flag_after_read'])) {
237 imap_setflag_full($result, (
string)$message[
'imap_uid'],
'\Seen', FT_UID);
242 drupal_set_message(t(
'Unable to connect to mailbox.'));
243 watchdog(
'mailinglist',
'Unable to connect to %mail', array(
'%mail' => $this->mail), WATCHDOG_ERROR);
255 extract($this->settings);
257 if (!function_exists(
'imap_open')) {
258 throw new Exception(t(
'The PHP IMAP extension must be enabled in order to use Mailinglist.'));
261 if ($type !=
'local') {
262 $result = imap_open($box, $name, $pass, NULL, 1);
265 $orig_home = getenv(
'HOME');
267 $new_home = realpath(drupal_get_path(
'module',
'node') .
'/../../');
268 if (!putenv(
"HOME=$new_home")) {
269 throw new Exception(t(
'Could not set home directory to %home.', array(
'%home' => $new_home)));
271 $result = imap_open($box,
'',
'', NULL, 1);
272 putenv(
"HOME=$orig_home");
281 extract($this->settings);
285 return '{' . $domain .
':' . $port . $extraimap .
'}' . $folder;
287 return '{' . $domain .
':' . $port .
'/pop3' . $extraimap .
'}' . $folder;
300 function get_part($stream, $msg_number, $mime_type, $structure = FALSE, $part_number = FALSE, $encoding) {
302 $structure = imap_fetchstructure($stream, $msg_number);
305 foreach ($structure->parameters as $parameter) {
306 if (drupal_strtoupper($parameter->attribute) ==
'CHARSET') {
307 $encoding = $parameter->value;
314 $text = imap_fetchbody($stream, $msg_number, $part_number, FT_PEEK);
315 if ($structure->encoding == ENCBASE64) {
316 return drupal_convert_to_utf8(imap_base64($text), $encoding);
318 elseif ($structure->encoding == ENCQUOTEDPRINTABLE) {
319 return drupal_convert_to_utf8(quoted_printable_decode($text), $encoding);
322 return drupal_convert_to_utf8($text, $encoding);
325 if ($structure->type == TYPEMULTIPART) {
327 while (list($index, $sub_structure) = each($structure->parts)) {
329 $prefix = $part_number .
'.';
331 $data = $this->
get_part($stream, $msg_number, $mime_type, $sub_structure, $prefix . ($index + 1), $encoding);
359 function get_parts($stream, $msg_number, $max_depth = 10, $depth = 0, $structure = FALSE, $part_number = 1) {
364 $structure = imap_fetchstructure($stream, $msg_number);
366 watchdog(
'mailinglist',
'Could not fetch structure for message number %msg_number', array(
'%msg_number' => $msg_number), WATCHDOG_NOTICE);
370 if ($structure->type == TYPEMULTIPART) {
372 if ($depth >= $max_depth) {
373 watchdog(
'mailinglist',
'Maximum recursion depths met in mailhander_get_structure_part for message number %msg_number.', array(
'%msg_number' => $msg_number), WATCHDOG_NOTICE);
377 foreach ($structure->parts as $index => $sub_structure) {
381 $prefix = $part_number .
'.';
383 $sub_parts = $this->
get_parts($stream, $msg_number, $max_depth, $depth + 1,
384 $sub_structure, $prefix . ($index + 1));
385 $parts = array_merge($parts, $sub_parts);
393 $part =
new stdClass();
394 $part->attributes = array();
395 $part->filename =
'unnamed_attachment';
396 if (!$part->filemime = $this->get_mime_type($structure)) {
397 watchdog(
'mailinglist',
'Could not fetch mime type for message part. Defaulting to application/octet-stream.', array(), WATCHDOG_NOTICE);
398 $part->filemime =
'application/octet-stream';
401 if ($structure->ifparameters) {
402 foreach ($structure->parameters as $parameter) {
403 switch (drupal_strtoupper($parameter->attribute)) {
406 $part->filename = $parameter->value;
410 $part->attributes[$parameter->attribute] = $parameter->value;
416 if ($structure->type != TYPETEXT && $structure->ifdparameters) {
417 foreach ($structure->dparameters as $parameter) {
418 switch (drupal_strtoupper($parameter->attribute)) {
421 $part->filename = $parameter->value;
425 $part->attributes[$parameter->attribute] = $parameter->value;
431 if (!empty($structure->id)) {
432 $part->id = $structure->id;
436 if (!$part->data = imap_fetchbody($stream, $msg_number, $part_number, FT_PEEK)) {
437 watchdog(
'mailinglist',
'No Data!!', array(), WATCHDOG_ERROR);
442 if ($structure->encoding == ENCBASE64) {
443 $part->data = imap_base64($part->data);
445 elseif ($structure->encoding == ENCQUOTEDPRINTABLE) {
446 $part->data = quoted_printable_decode($part->data);
449 elseif ($structure->type == TYPETEXT) {
450 $part->data = imap_utf8($part->data);
463 static $primary_mime_type = array(
'text',
'multipart',
'message',
'application',
'audio',
'image',
'video',
'other');
464 $type_id = (int) $structure->type;
465 if (isset($primary_mime_type[$type_id]) && !empty($structure->subtype)) {
466 return $primary_mime_type[$type_id] .
'/' . drupal_strtolower($structure->subtype);
480 $unread_messages = array();
481 $number_of_messages = imap_num_msg($result);
482 for ($i = 1; $i <= $number_of_messages; $i++) {
483 $header = imap_header($result, $i);
484 if ($header->Unseen ==
'U' || $header->Recent ==
'N') {
485 $unread_messages[] = $i;
488 return $unread_messages;
502 extract($this->settings);
503 dpm(
"MailinglistPhpImapRetreive::retreive_message");
504 $raw_headers = imap_fetchheader($result, $msg_number, FT_PREFETCHTEXT);
506 $header = imap_headerinfo($result, $msg_number);
509 if (!isset($header->subject)) {
510 $header->subject =
'';
514 $mimeparts = $this->
get_parts($result, $msg_number);
516 $body_text = $this->
get_part($result, $msg_number,
'text/plain', FALSE, FALSE, $encoding);
517 $body_html = $this->
get_part($result, $msg_number,
'text/html', FALSE, FALSE, $encoding);
518 if (!$body_text && $body_html) {
519 $body_text = $body_html;
521 elseif ($body_text && !$body_html) {
522 $body_html = $body_text;
525 if (!$body_text && !$body_html && !$mimeparts) {
529 $imap_uid = ($type ==
'pop3') ? $this->
fetch_uid($msg_number) : imap_uid($result, $msg_number);
530 $message = compact(
'header',
'raw_headers',
'body_text',
'body_html',
'mimeparts',
'imap_uid');
541 imap_close($result, CL_EXPUNGE);
550 extract($this->settings);
552 $fp = fsockopen($domain, $port);
554 $buf = fgets($fp, 1024);
555 fwrite($fp,
"USER $name\r\n");
556 $buf = fgets($fp, 1024);
557 fwrite($fp,
"PASS $pass\r\n");
558 $buf = fgets($fp, 1024);
559 fwrite($fp,
"UIDL $msg_number\r\n");
560 $retval=fgets($fp, 1024);
561 fwrite($fp,
"QUIT\r\n");
562 $buf = fgets($fp, 1024);
565 return drupal_substr($retval, 6, 30);
Retrieve messages using PHP IMAP library.
fetch_uid($msg_number)
Fetch UID for a message in a POP mailbox.
purge_message($message)
mark message for deletion
get_setting($name, $def=NULL)
get_settings()
close_mailbox($result)
Close a mailbox.
edit_form_validate(&$form, &$form_state)
Implements ctools_export_ui::edit_form_validate().
get_unread_messages($result)
Obtain the number of unread messages for an imap stream.
log($str, $level=self::LOG_NOTICE, $parms=array())
log()
retrieve_message($result, $msg_number)
Retrieve individual messages from an IMAP result.
edit_form_submit(&$form, &$form_state)
Implements ctools_export_ui::edit_form_submit().
get_parts($stream, $msg_number, $max_depth=10, $depth=0, $structure=FALSE, $part_number=1)
Returns an array of parts as file objects.
_mailinglist_decode_password($code)
_mailinglist_decode_password
mailbox_string()
Constructs a mailbox string based on mailbox object.
get_message_list($max=0)
Returns a list of messages that are available.
get_mime_type(&$structure)
Retrieve MIME type of the message structure.
test()
Test connection to a mailbox.
edit_form(&$form, &$form_state)
Implements ctools_export_ui::edit_form().
get_part($stream, $msg_number, $mime_type, $structure=FALSE, $part_number=FALSE, $encoding)
Returns the first part with the specified mime_type.
Retrieve messages from a Mailinglist Mailbox.
open_mailbox()
Establish IMAP stream connection to specified mailbox.