Kuzevich

Kuzevich

Понедельник, 20 августа 2018 20:41

PHP скрипт отправки почты через SMTP SSL mail.ru

Выкладываю для общего пользования пример PHP-скрипта для отправки почты через SMTP ssl mail.ru

 

<?php
function get_data($smtp_conn)
{
  $data="";
  while($str = fgets($smtp_conn,515)) 
  {
    $data .= $str;
    if(substr($str,3,1) == " ") { break; }
  }
  return $data;
}
 
$header="Date: ".date("D, j M Y G:i:s")." +0700\r\n"; 
$header.="From: =?windows-1251?Q?".str_replace("+","_",str_replace("%","=",urlencode('ВашеИмя')))."?= <ВашаПочта@mail.ru>\r\n"; 
$header.="X-Mailer: The Bat! (v3.99.3) Professional\r\n"; 
$header.="Reply-To: =?windows-1251?Q?".str_replace("+","_",str_replace("%","=",urlencode('ВашеИмя')))."?= <ВашаПочта@mail.ru>\r\n";
$header.="X-Priority: 3 (Normal)\r\n";
$header.="Message-ID: <172562218.".date("YmjHis")."@mail.ru>\r\n";
$header.="To: =?windows-1251?Q?".str_replace("+","_",str_replace("%","=",urlencode('ИмяПолучателя')))."?= <АдресПолучателя@gmail.com>\r\n";
$header.="Subject: =?windows-1251?Q?".str_replace("+","_",str_replace("%","=",urlencode('проверка')))."?=\r\n";
$header.="MIME-Version: 1.0\r\n";
$header.="Content-Type: text/plain; charset=windows-1251\r\n";
$header.="Content-Transfer-Encoding: 8bit\r\n";
 
 
$text="привет, проверка связи.";
 
$smtp_conn = fsockopen("ssl://smtp.mail.ru", 465,$errno, $errstr, 10);
$data = get_data($smtp_conn);
 
$code = substr($data,0,3);
print 'Connection:'.$data;
print '<br>';
 
fputs($smtp_conn,"EHLO mail.ru\r\n");
$data = get_data($smtp_conn);
 
$test='qwe';
 
$code = substr($data,0,3);
echo 'EHLO:'.$data;
print '<br>';
 
fputs($smtp_conn,"AUTH LOGIN\r\n");
$data = get_data($smtp_conn);
 
$code = substr($data,0,3);
echo 'AUTH:'.$data;
print '<br>';
 
fputs($smtp_conn,base64_encode("ВашаПочта@mail.ru")."\r\n");
$data = get_data($smtp_conn);
 
$code = substr($data,0,3);
echo $data;
print '<br>';
 
fputs($smtp_conn,base64_encode("ВашПароль")."\r\n");
$data = get_data($smtp_conn);
 
$code = substr($data,0,3);
echo 'pass:'.$data;
print '<br>';
 
fputs($smtp_conn,"MAIL FROM:ВашаПочта@mail.ru\r\n");
$data = get_data($smtp_conn);
 
$code = substr($data,0,3);
echo 'MAIL:'.$data;
print '<br>';
 
fputs($smtp_conn,"RCPT TO:АдресПолучателя@gmail.com\r\n");
$data = get_data($smtp_conn);
 
$code = substr($data,0,3);
echo 'RCPT:'.$data;
print '<br>';
 
fputs($smtp_conn,"DATA\r\n");
$data = get_data($smtp_conn);
 
$code = substr($data,0,3);
echo 'DATA:'.$data;
print '<br>';
 
fputs($smtp_conn,$header."\r\n".$text."\r\n.\r\n");
$data = get_data($smtp_conn);
 
$code = substr($data,0,3);
echo 'header:'.$data;
print '<br>';
 
fputs($smtp_conn,"QUIT\r\n");
$data = get_data($smtp_conn);
 
$code = substr($data,0,3);
echo 'QUIT:'.$data;
print '<br>';
 
?>

Столкнулся с проблемой отправки писем из интернет-магазина на базе ocStore 2.3.0.2.3

Для начала проверьте настройки магазина в админке: Система-Настройки

Откройте редактирование магазина и на вкладке почта установите:

Почтовый протокол: SMTP
Параметры функции mail оставьте пустым
SMTP хост: ssl://smtp.mail.ru
SMTP логин: вашапочта@mail.ru
SMTP пароль: вашпароль
SMTP порт: 465
SMTP таймаут: 60

Затем посмотрите логи /log/error.log

У меня там была ошибка: PHP Fatal error:  Uncaught Exception: Error: RCPT TO not accepted from server! in /var/www/clients/client1/web1/web/system/library/mail.php:340

Не работала форма обратной связи и не приходили на почту заказы клиентов.

Я начал с исправления формы обратной связи.

Для этого нужно поправить файл /catalog/controller/information/contact.php

исправить строку
$mail->setReplyTo($this->request->post['email']);
на
$mail->setReplyTo($this->config->get('config_email'));

Если все исправили, то при отправке формы получите сообщение: Ваш запрос был успешно отправлен администрации магазина!

 Для того чтобы приходило оповещение о заказе, нужно исправить файл /system/storage/modification/catalog/model/checkout/order.php 

в 3х местах найти строки
$mail->setTo($order_info['email']);
или 
$mail->setTo($this->config->get('config_email'));

и заменить их на:
$mail->setTo($this->config->get('config_email'));
$mail->setReplyTo($this->config->get('config_email'));

Если все получилось, то в конце оформления заказа, будете получать сообщение:

Заказ успешно сформирован!

Ваш заказ был успешно сформирован!

Unity отправка почты, в том числе и с мобильных устройств Android и iOS
Столкнулся недавно с казалось бы тривиальной задачей "сохранение данных из приложения и отправка их на email", которая не дала мне спать пару ночей, пока я с ней разбирался.

Итак по порядку...

Во первых программа должна сохранять файл.
В данном случае я для примера в процедуре Start() пишу CSV файл с тестовым набором данных.
Обратите внимание, что для сохранения файла желательно использовать путь Application.persistentDataPath, поскольку он указывает на пользовательскую папку Вашего приложения на любом устройстве и позволяет туда сохранять все что угодно.(подробнее здесь: https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html )

    void Start () {
        FileName = Application.persistentDataPath + "/fio.csv";
 
        string text = "Текст для проверки;2;3;"+System.DateTime.Now.ToString("dd.MM.yyyy hh:mm:ss");
        string text1 = "Текст для проверки1;2;3";
        string text2 = "Текст для проверки2;2;3";
 
        try
        {
            StreamWriter sw = File.AppendText(FileName);
 
            sw.WriteLine(text);
            sw.WriteLine(text1);
            sw.WriteLine(text2);
 
            sw.Close();
        }
        catch (System.Exception e)
        {
            Debug.Log(e.ToString());
        }
 
    }

На сцене создаем UI->text (поле в которое будем выводить сообщение)
И кнопку на которую повесим функцию SendEmail()

	 public void SendEmail()
    {
        try
        {
            MailMessage mail = new MailMessage();
            SmtpClient SmtpServer = new SmtpClient("smtp.mail.ru", 25);
 
            mail.From = new MailAddress("вашапочта@mail.ru");
            mail.To.Add("почта_адресата@gmail.com");
 
            mail.Subject = "Test Mail from Unity";
            mail.Body = "This is for testing SMTP mail from Mail.ru";
 
            Attachment data = new Attachment(FileName, System.Net.Mime.MediaTypeNames.Application.Octet);
            // Add time stamp information for the file.
            System.Net.Mime.ContentDisposition disposition = data.ContentDisposition;
            disposition.CreationDate = System.IO.File.GetCreationTime(FileName);
            disposition.ModificationDate = System.IO.File.GetLastWriteTime(FileName);
            disposition.ReadDate = System.IO.File.GetLastAccessTime(FileName);
 
            mail.Attachments.Add(data);
 
            SmtpServer.Credentials = (ICredentialsByHost) new NetworkCredential("вашапочта@mail.ru", "ВашПароль");
 
            SmtpServer.EnableSsl = true;
            ServicePointManager.ServerCertificateValidationCallback =
                delegate (object s, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
                { return true; };
 
 
            SmtpServer.Send(mail);
 
            Debug.Log("mail Sent");
            GameObject.Find("Text").GetComponent<Text>().text = "mail Sent";
        }
        catch (Exception ex)
        {
            Debug.Log(ex.ToString());
            GameObject.Find("Text").GetComponent<Text>().text = ex.ToString();
        }
    }



Для того чтобы работала криптография и smtpsend, подключаем библиотеки

using System.IO;
using System.Net;
using System.Net.Mail;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System;
using UnityEngine.UI;


Первая проблема - с портами, у меня заработал только сервис mail.ru, поскольку поддерживает классический 25 порт.
По портам из помощи yandex'a и google'a не пошло.
(хотя в дальнейшем я разобрался, благодаря материалу на Хабре, чтобы работал 465 порт оставляете в SmtpClient 25 порт, затем пишете smtpClient.EnableSsl = true; тогда соединение устанавливается через 25 порт в незашифрованном виде, а затем переключается в защищенный режим.)

Готово, из самого Unity3D или windows-приложения все отправляется, но если собрать для мобильного устройства - не работает!

Получаем ошибку типа: Cannot implicitly convert type System.Net.NetworkCredential to System.Net.ICredentialsByHost

Дело в том, что для мобильного устройства по умолчанию собирается с .Net 2.0 Subset (это сделано для уменьшения размера собранного приложения, за счет отказа от ненужных функций фреймворка).

Таким образом нам нужно зайти в настройки плеера и поменять Api Compatibility Level на .Net 2.0. (File->Build Settings->Player Settings->Api Compatibility Level)

Ок. Теперь работает на Android. Из под iOS все равно не отправляется.
Получаем ошибку:
MissingMethodException: Method not found: 'Default constructor not found...ctor() of System.Net.Configuration.MailSettingsSectionGroup'

Оказывается это известный баг с 2015 года, который до сих пор не пофиксили: https://issuetracker.unity3d.com/issues/il2cpp-crashes-when-using-smtpclient

Решение простое: создать в корне папки assets файл link.xml со следующим содержимым:
<linker> <assembly fullname="System"> <type fullname="System.Net.Configuration.MailSettingsSectionGroup" preserve="all"/> <type fullname="System.Net.Configuration.SmtpSection" preserve="all"/> <type fullname="System.Net.Configuration.SmtpNetworkElement" preserve="all"/> <type fullname="System.Net.Configuration.SmtpSpecifiedPickupDirectoryElement" preserve="all"/> </assembly> </linker>

обратите внимание, если Вы возьмете этот код из приведенной ссылки на issuetracker - там в слове SmtpSpecifiedPickupDirectoryElement в слове Directory между t и o какой то какой то странный символ и с ним ничего не работает, поэтому лучше скопируйте у меня, либо скачайте у меня же готовый файл.

Пересоберите проект и все должно запуститься.
Если у Вас есть, что добавить - пишите в комментариях.

 

Сегодня я расскажу Вам как в Unity3D сделать перетаскивание объектов в предназначенные для них места с помощью Drag&Drop и как сделать анимацию прыгающих значков. Не претендую на истину в последней инстанции с точки зрения "как надо", пишу о том, как я сделал рабочее решение, работающее не только с мышкой, но и на мобильных устройствах с тачскринами. Для начала создаем под Main Camera - Canvas (область отображения интерфейса) Внутри него создаем 4 картинки (UI->image)

Две картинки переименовываем в place1 и place2 и задаем им цвета потемнее (это будут места, куда мы сможем перетащить объекты) Другие две переименовываем в item1 и item2 и задаем им цвета посветлее (это будут перетаскиваемые элементы, которые мы должны положить на соответствующие места)

Добавляем для наших item'ов компоненты: Phisics 2D->RigidBody 2D и Phisics 2D->Box Collider 2D

 

А на объекты place1 и place2 добавляем только коллайдеры Не забудьте откорректировать размер коллайдеров под размер объекта и поставить у них галку Is Trigger

 

Создаем C# скрипт DragHandler.

Добавляем:

using UnityEngine.EventSystems; 
using UnityEngine.UI;

видим класс:

public class DragHandler : MonoBehaviour {

добавляем интерфейсы:

public class DragHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler

Добавляем переменные:

public static GameObject itemBeingDragged; 
Vector3 HomePosition; 
Rigidbody2D rb; 
GameObject ObjectUnder; 
string ObjectUnderName="";

Реализуем интерфейсы:

#region IBeginDragHandler implementation
 
public void OnBeginDrag(PointerEventData eventData)
{
//Запоминаем перетаскиваемый объект и его начальную позицию
itemBeingDragged = gameObject;
ObjectUnderName = "";
 
}
 
#endregion
 
#region IDragHandler implementation
 
public void OnDrag(PointerEventData eventData)
{
//используем RigidBody для отлова пересечений (collider)
rb.MovePosition(eventData.position);
}
 
#endregion
 
#region IEndDragHandler implementation
 
public void OnEndDrag(PointerEventData eventData)
{
 
itemBeingDragged = null;
 
//проверяем на место ли перетащили
if (ObjectUnderName == "place1" && this.name == "item1")
{
transform.position = ObjectUnder.transform.position;
//тут можем что то еще делать
}
else if (ObjectUnderName == "place2" && this.name == "item2")
{
transform.position = ObjectUnder.transform.position;
//тут можем что то еще делать
}
else
{
//если нет пересечения возвращаем в исходное положение
transform.position = HomePosition;
}
 
}
 
#endregion

Добавляем обработку коллизий:

void OnTriggerEnter2D(Collider2D myCollision)
{
// определение столкновения с двумя разноименными объектами
ObjectUnder = myCollision.gameObject;
ObjectUnderName = ObjectUnder.name;
}
 
void OnTriggerExit2D(Collider2D myCollision)
{
// определение столкновения с двумя разноименными объектами
ObjectUnder = myCollision.gameObject;
ObjectUnderName = "";
}

Теперь добавляем наш скрипт к объектам item1 и item2

Проверяем, что все работает. Зеленый квадрат ложится только на зеленый, голубой на синий.

В принципе все, но добавим немного анимации для перетаскиваемых объектов (подпрыгивание)

Добавляем переменные:

//подпрыгивание объектов
Vector3 placePosition;
float DeltaPos;
float MyVector;

В процедуру Start() добавляем сохранение начальных значений:

//подпрыгивание объектов
placePosition = transform.position;
MyVector = 0.2f;
 

И анимируем прыжки в процедуре Update void Update()

void Update()
{
//подпрыгивание объектов
if (DeltaPos > 1) MyVector = -0.2f;
if (DeltaPos < -1) MyVector = 0.2f;
DeltaPos += MyVector;
 
if (itemBeingDragged == null && ObjectUnderName == "")
{
transform.position = placePosition + new Vector3(0.0f, DeltaPos, 0.0f); ;
}
}

Вот теперь все. Если вдруг непонятно описал, то можете скачать рабочий проект для unity3D отсюда.