Отправка и получение писем. php imap

alias

Новичок
Вот функция для подготовки письма:

PHP:
public function compose($form) {

        $salt = md5(time());
        $pre = '<html><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body>';
        $post = '</body></html>';
        $this->to = $form['to'];
        $this->subject = quoted_printable_encode($form['subject']);
        $this->headers = 'From: ' . $this->login . PHP_EOL;
        $this->headers .= 'Reply-To: ' . $this->login . PHP_EOL;
        $this->headers .= 'To: ' . $this->to . PHP_EOL;
        $this->headers .= 'Date: ' . date('r') . PHP_EOL;
        $this->headers .= 'Subject: ' . $this->subject . PHP_EOL;
        $this->headers .= "MIME-Version: 1.0" . PHP_EOL;
        if (isset($form['attachments']) && sizeof($form['attachments'])) {
            $this->headers .= "Content-Type: multipart/mixed; boundary=\"mixed-" . $salt . "\"" . PHP_EOL . PHP_EOL;
            $this->headers .= "--mixed-" . $salt . PHP_EOL;
        }
        $this->headers .= "Content-Type: multipart/alternative; boundary=\"alt-" . $salt . "\"" . PHP_EOL;
        $this->body = "--alt-" . $salt . PHP_EOL;
        $this->body .= "Content-Transfer-Encoding: quoted-printable" . PHP_EOL;
        $this->body .= "Content-Type: text/html; charset=utf-8" . PHP_EOL . PHP_EOL;
        $this->body .= quoted_printable_encode($pre . $form['body'] . $post) . PHP_EOL . PHP_EOL;
        $this->body .= "--alt-" . $salt . '--' . PHP_EOL;

        if (isset($form['attachments']) && sizeof($form['attachments'])) {
            foreach ($form['attachments'] as $v) {
                $attachment = chunk_split(base64_encode(file_get_contents($this->root . '/tmp/' . $v)));
                $this->body .= PHP_EOL . "--mixed-" . $salt . PHP_EOL;
                $this->body .= "Content-Type: application/octet-stream; name=\"" . $v . "\"" . PHP_EOL;
                $this->body .= "Content-Disposition: attachment; filename=\"" . $v . "\"" . PHP_EOL;
                $this->body .= "Content-Transfer-Encoding: base64" . PHP_EOL . PHP_EOL;
                $this->body .= $attachment . PHP_EOL;
            }
            $this->body .= "--mixed-" . $salt . "--" . PHP_EOL;
        }

        return $this;
    }
Отправка:

PHP:
public function send() {
  $data['errors'] = array();
  if (!$this->to) {
  $data['errors'][] = 'Empty receiver';
  }
  if (!$this->body) {
  $data['errors'][] = 'Empty body';
  }
  if (!$this->headers) {
  $data['errors'][] = 'Empty headers';
  }
  if (!sizeof($data['errors'])) {
  $connect = imap_open($this->imap_url . 'INBOX', $this->login, $this->password);
  $msg = $this->headers . $this->to . $this->subject . $this->body;
  imap_append($connect, $this->imap_url . 'INBOX.Sent', $msg);
  return imap_mail($this->to, $this->subject, $this->body, $this->headers);
  } else {
  $msg = $this->headers . $this->to . $this->subject . $this->body;
  imap_append($connect, $this->imap_url . 'INBOX.Drafts', $msg);
  return $data;
  }
  }
Вот результат imap_fetchbody($connect, $v->msgno, 1, FT_PEEK);

PHP:
--alt-25ffea7b10fd64171b1208cef1d0430e Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8 <html><meta http-equiv=3D"Content-Type" content=3D"text/html charset=3Dutf-= 8"></head><body><p>asddas</p></body></html> --alt-25ffea7b10fd64171b1208cef1d0430e--
Из-за служебной инфы при перекодировке возвращает пустую строку.

При отправке таких писем на gmail - все ок.
Я не могу понять, или у меня проблема в заголовках или я считываю не так?
 
Последнее редактирование:

alias

Новичок
В процессе попыток решить проблему - выявил следующее:
1) gmail высылает письма с типом части тела письма равному 1(что соответствует imap_8bit)
и разные почтовые службы высылают с разными типами не соответствующим выбранному кодированию. Как решить такое?

P.S. Я высылаю в quoted printable, но тип почему-то проставляется 1
 

WMix

герр M:)ller
Партнер клуба
imap не самый удачный выбор для отправки писем, используй smpt
 

alias

Новичок
смтп всмысле mail? как это отразится на заголовках? И как быть с получением? Я так и не пойму как перекодировать письма.
 
Последнее редактирование:

Фанат

oncle terrible
Команда форума
Я согласен с предыдущим оратором.
Сам я когда-то тоже занимался такими извращениями, шараша тело сообщения вручную. Аж ностальгия пробила.
Но с тех пор много воды утекло, и я все позабыл.
Поэтому рекомендую тупо взять PHPMailer и отправлять через него. Если там нету отправки через имап (а я думаю что есть) то отправлять через смтп. А поучать через имап, старым своим кодом.
 

alias

Новичок
Я согласен с предыдущим оратором.
Сам я когда-то тоже занимался такими извращениями, шараша тело сообщения вручную. Аж ностальгия пробила.
Но с тех пор много воды утекло, и я все позабыл.
Поэтому рекомендую тупо взять PHPMailer и отправлять через него. Если там нету отправки через имап (а я думаю что есть) то отправлять через смтп. А поучать через имап, старым своим кодом.
Проблема в том что тип получаю неверный с почтовых серверов.
 

Фанат

oncle terrible
Команда форума
ничего не понял. у тебя проблема с отправкой или с получением?
Ты можешь точно сформулировать проблему?
 

alias

Новичок
Проблема в считывании тела сообщения, прикрепленные файлы считываются отлично, но вот само сообщение нет. Параметр type в части, получаемый от почтовых сервисов отличается от верного параметра для кодирования. Так же письмо отправляемое мной с использованием функции описанной выше при разборе указывает на type = 1, что соответствует функции imap_8bit для декодирования, но я отправляю в quote printable что и пишу в заголовке.

Я могу также выложить функцию для получения писем. Я не могу понять где у меня проблема в считывании или в отправке. Могу предположить что в считывании, так как считывание превращается в подстраивание под каждый сервис отдельно, а это должно быть одинаково для всех писем.
 
Последнее редактирование:

alias

Новичок
вот функция получения писем из папки
PHP:
public function getDir($folder, $dir) {
  $connect = imap_open($this->imap_url . 'INBOX', $this->login, $this->password);
  imap_reopen($connect, $this->imap_url . $dir);
  $errors = imap_errors();
  $data['success'] = false;
  if (!$connect) {
  $data['error'] = '<h2 class="status">Ошибка соединения</h2>';
  } else {
  if ($errors && sizeof($errors) > 0) {
  imap_createmailbox($connect, imap_utf7_encode($this->imap_url . $dir));
  }
  $check = imap_check($connect);
  if ($check->Nmsgs == 0) {
  $data['error'] = '<h2 class="status">Сообщений нет</h2>';
  } elseif (!$header = imap_fetch_overview($connect, "{$check->Nmsgs}:1")) {
  $data['error'] = '<h2 class="status">Сообщений нет</h2>';
  } else {
  $header = array_reverse($header);
  $data['success'] = true;
  mb_internal_encoding('UTF-8');
  foreach ($header as $k => $v) {
  $from = imap_mime_header_decode($v->from);
  $subject = imap_mime_header_decode($v->subject);
  $body = $this->extract_body($connect, $v->msgno);
  $data['messages'][$k] = array(
  'subject' => $subject[0]->text,
  'from' => array($from[0]->text, preg_replace('/[> <]/', '', $from[1]->text)),
  'date' => $this->getDate(strtotime($v->date)),
  'seen' => $v->seen,
  'dir' => $folder,
  'msgno' => $v->msgno,
  'attachment' => $this->extract_attachments($connect, $v->msgno),
  'body' => trim(strip_tags($body['out']))
  );
  if (!$data['messages'][$k]['from'][1]) {
  $data['messages'][$k]['from'][1] = $data['messages'][$k]['from'][0];
  $data['messages'][$k]['from'][0] = $this->user->getVar('name');
  }
  }
  imap_close($connect);
  }
  }
  return $data;
  }
вот функция получения сообщения из тела:

PHP:
protected function extract_body($connection, $message_number) {
  $structure = imap_fetchstructure($connection, $message_number);
  $body = array();
  for ($i = 0; $i < count($structure->parts); $i++) {
  $is_attachment = false;

  if ($structure->parts[$i]->ifdparameters) {
  foreach ($structure->parts[$i]->dparameters as $object) {
  if (strtolower($object->attribute) == 'filename') {
  $is_attachment = true;
  }
  }
  }

  if ($structure->parts[$i]->ifparameters) {
  foreach ($structure->parts[$i]->parameters as $object) {
  if (strtolower($object->attribute) == 'name') {
  $is_attachment = true;
  }
  }
  }

  if (!$is_attachment) {
  $body[$i]['data'] = imap_fetchbody($connection, $message_number, $i + 1, FT_PEEK);
  $body[$i]['charset'] = '';
  $body[$i]['type'] = $structure->parts[$i]->type;
  if (isset($structure->parts[$i]->parameters) && sizeof($structure->parts[$i]->parameters)) {
  foreach ($structure->parts[$i]->parameters as $object) {
  if ($object->attribute == 'charset') {
  $body[$i]['charset'] = strtoupper($object->value);
  }
  }
  }
  $body[$i]['out'] = $this->getdecodevalue($body[$i]['data'], $structure->parts[$i]->type);
  if ($body[$i]['charset'] && !in_array($body[$i]['charset'], array('UTF-8', 'UTF8'))) {
  $body[$i]['out'] = mb_convert_encoding($body[$i]['out'], 'UTF-8', $body[$i]['charset']);
  }
  }
  }
  return $body;
  }
 
Последнее редактирование:
Сверху