Отправка SMS
Для того, чтобы программно отправлять SMS из QLua, или C#, для начала перейдите по этой ссылке. Вы попадете на сайт сервиса "SMS ЦЕНТР"
Нажав на кнопку "РЕГИСТРАЦИЯ В СЕРВИСЕ", Вы увидите форму регистрации, заполните все поля, обязательно укажите свой телефон.
Нажмите на кнопку "Зарегистрироваться".
Затем нажмите на кнопку "Мой кабинет":
Далее, нажмите на ссылку "Подтвердить номер", затем на кнопку "Получить SMS", Вам на телефон придет SMS с кодом, введите его в поле слева от кнопки, и нажмите ниже кнопку "Подтвердить номер"
После этого на Вашем счету появятся 15 подарочных рублей для тестирования.
Цены на отправку SMS вы можете посмотреть в разделе "Мой кабинет".
На этом настройку на данном сайте можно считать завершенной.
Для использования данного сервиса в QLua нужно скачать данный архив, извлечь из него 3 папки: "lua", "mime", "socket". И поместить их в корневой каталог терминала QUIK (туда, где файл info.exe).
1 2 3 4 5 6 7 8 9 10 11 12 | http = require('socket.http'); login = "MyLogin"; -- Ваш логин на сайте smsc.ru password = "MyPassword"; -- Ваш пароль на сайте smsc.ru phone = "79999999999"; -- Ваш номер телефона msg = "Текст сообщения"; function main() message(tostring(http.request ("http://smsc.ru/sys/send.php?login="..login.."&psw="..password.."&phones="..phone.."&mes="..msg))); end; -- Если Вы нигде не ошиблись, то получите SMS на телефон от "SMSC.RU" и сообщение в терминале вида: "OK - 1 SMS, ID - 1" |
Для отправки SMS из C# перейдите по данной ссылке и скачайте первый файл "smsc_api.cs"
Положите его в папку с Вашим проектом C# (там, где папка bin) и добавьте его в проект, нажав правой кнопкой мыши по названию проекта, перейдя по пути: "Добавить" -> "Существующий элемент...", выбрав данный файл в папке проекта и нажав кнопку добавить.
Далее, нажмите правой кнопкой мыши по ссылке "References" Вашего проекта и выберите "Добавить ссылку...".
В открывшемся окне найдите "System.Web", поставьте галочку слева от него и нажмите на кнопку "ОК".
Теперь необходимый функционал подключен к проекту!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | private void button1_Click(object sender, EventArgs e) { SMSC smsc = new SMSC(); // Создает экземпляр класса для работы с сервисом string[] r = smsc.send_sms("79999999999", "Проверочное SMS"); // Отправляет SMS на номер string Result = ""; if(r.Length > 2) // Если ошибки нет { Result += "id = " + r[0] + Environment.NewLine + "количество sms = " + r[1] + Environment.NewLine + "стоимость = " + r[2] + Environment.NewLine + "баланс = " + r[3] + Environment.NewLine; } else // Если ошибка есть { Result += "id = " + r[0] + Environment.NewLine + "код ошибки = " + r[1] + Environment.NewLine; } // Выводит результат MessageBox.Show(Result); } |
ОТПРАВКА E-MAIL
Для того, чтобы отправить письмо на эл.почту (в т.ч. с прикрепленным файлом) из QLua скачайте архив EmailSender.zip, в нем находятся 2 файла: SenderEmail.dll - библиотека (для Quik 8 x64 используйте эту dll), которая подключается к скрипту QLua и Email.exe - приложение (почтовый клиент), написанное на C#, которое автоматически запускается и завершается и видно только в виде иконки (логотип сайта) в области уведомлений (правый нижний угол рабочего стола Windows). Оба этих файла нужно извлечь из архива и поместить в корневой каталог терминала QUIK (где info.exe).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | require("SenderEmail"); -- Подключает SenderEmail.dll Run = true; -- Флаг поддержания работы скрипта -- Основная функция скрипта, пока выполняется она, работает скрипт function main() -- Отправляет письмо SenderEmail.SendEmail( "smtp.mail.ru", -- SMTP сервер "test@mail.ru", -- Ваш логин "MyPassword", -- Ваш пароль "test@mail.ru", -- Email получателя "test@mail.ru", -- Email отправителя "Тема", -- Тема письма "Текст письма", -- Текст письма "Тест.txt" -- Путь к файлу вложения относительно Email.exe, либо полный путь -- (если не нужно, то оставить пустым (""), либо вообще убрать) ); -- !!! Не отправляйте новое письмо, пока не дождетесь результата отправки предыдущего в функции EmailResult() while Run do sleep(10); end; -- Поддерживает работу функции main() end; -- Функция обратного вызова, вызывается автоматически после отправки письма function EmailResult(res) -- Если отправка прошла успешно в res будет "OK", при ошибке "Ошибка отправки email: Текст ошибки" message(res); end; -- Функция вызывается при остановке скрипта function OnStop() Run = false; -- Сбрасывает флаг, чтобы завершить цикл while в функции main() end; |
Если у Вас при использовании данного варианта отправки появятся ошибки, или Вы захотите внести какие-то коррективы в код, то можете скачать готовое решение для Visual Studio 2015 и перестроить (скомпилировать) его на своем компьютере.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | //SenderEmail.cpp 2015(c)QuikLuaCSharp.ru #include <windows.h> // Подключает основной функционал для работы с ОС Windows #include <thread> // Подключает функционал для работы с потоками #include <tlhelp32.h> // Подключает функционал для получения информации о запущенных процессах //=== Необходимые для Lua константы ============================================================================// #define LUA_LIB #define LUA_BUILD_AS_DLL //=== Заголовочные файлы LUA ===================================================================================// extern "C" { #include "Lua\lauxlib.h" #include "Lua\lua.h" } //=== Получает указатели на выделенную именованную память =====================================================// // Имя для выделенной памяти для отправки Email TCHAR EmailMemory[] = TEXT("EmailMemory"); // Создаст, или подключится к уже созданной памяти с таким именем HANDLE hFileMapEmail = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, 4096, EmailMemory); //КОНСТАНТЫ СОСТОЯНИЯ ПАМЯТИ const char *QR = "_QR_"; // Память ожидает чтения Qlua (Qlua Read) const char *QW = "_QW_"; // Память ожидает записи Qlua (Qlua Write) const char *CR = "_CR_"; // Память ожидает чтения C# (C# Read) const char *CW = "_CW_"; // Память ожидает записи C# (C# Write) volatile PBYTE pb = NULL; // Указатель на байты данных памяти TCHAR szPath[] = TEXT("Email.exe"); // Путь почтового клиента STARTUPINFO si; // Необходимые для запуска процесса структуры PROCESS_INFORMATION pi; // bool SMTPclientWasRunning = false; // Флаг, что почтовый клиент уже был запущен ранее, чтобы не запустить еще одну копию // Функция проверяет запущен ли процесс (программа) по его имени bool IsProcessRun(const char * const processName) { HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); Process32First(hSnapshot, &pe); while (1) { if (strcmp(pe.szExeFile, processName) == 0) return true; if (!Process32Next(hSnapshot, &pe)) return false; } } //=== Стандартная точка входа для DLL ==========================================================================// BOOL APIENTRY DllMain(HANDLE hModule, DWORD fdwReason, LPVOID lpReserved) { //Каждому событию соответствует свое значение аргумента fdwReason, передаваемого функции DllMain при его возникновении switch (fdwReason) { case DLL_PROCESS_ATTACH: // Подключение DLL // Если почтовый клиент еще не запущен if (!IsProcessRun("Email.exe")) { //Запускает почтовый клиент memset(&si, 0, sizeof(si)); si.cb = sizeof(si); memset(&pi, 0, sizeof(pi)); CreateProcess(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); } else { SMTPclientWasRunning = true; // Запоминает, что почтовый клиент уже был запущен (до подключения данной DLL) } return TRUE; case DLL_PROCESS_DETACH: // Отключение DLL // Если почтовый клиент был запущен данной DLL if (!SMTPclientWasRunning) { //Закрывает почтовый клиент TerminateProcess(pi.hProcess, 0); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); } break; case DLL_THREAD_ATTACH: // Создание нового потока break; case DLL_THREAD_DETACH: // Завершение потока break; } return TRUE; } //=== Вспомогательные функции ==================================================================================// //Функции проверки состояний памяти static bool QluaReadReady() // Память ожидает чтения Qlua (Qlua Read) { if (pb[0] == '_' && pb[1] == 'Q' && pb[2] == 'R' && pb[3] == '_') return true; return false; } static bool QluaWriteReady() // Память ожидает записи Qlua (Qlua Write) { if (pb[0] == '_' && pb[1] == 'Q' && pb[2] == 'W' && pb[3] == '_') return true; return false; } //Функция читает память "EmailMemory" с периодичностью в 10 миллисекунд, пока не получит результат отправки email от C#, //затем передает результат в QLua функцию EmailResult(), если она есть в скрипте static int WaitingEmailResult(lua_State *L) { lua_getglobal(L, "EmailResult"); //Находит в стеке Lua функцию по ее названию и помещает ее наверх стека if (lua_isfunction(L, -1)) // Если на верху стека функция { int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); //Получает индекс функции в специальной внутренней таблице (реестре) Lua // Ждет, пока C# запишет в память результат отправки email (память будет ожидать чтения Qlua) while (!QluaReadReady()) { Sleep(10); } // Пауза в 10 миллисекунд lua_rawgeti(L, LUA_REGISTRYINDEX, callbackRef); // Достает функцию из реестра Lua по ранее полученному индексу и помещает в стек if (lua_isfunction(L, -1)) // Если на верху стека функция { lua_pushstring(L, (char*)(pb + 4)); //Записывает в Lua-стек полученный результат (без управляющей константы) lua_call(L, 1, 1); //Вызывает выбранную функцию в скрипте QLua, передавая в нее 1 параметр (L - стек, 1 - количество передаваемых параметров, 1 - количество возвращаемых значений(нужно, чтобы обновлять стек)) } //Очищает память for (int i = 0; i < 4096; i++)pb[i] = '\0'; // Устанавливает константу "_QW_", сообщая тем самым, что память ожидает записи QLua memcpy(pb, QW, 4); } //Закрывает представление UnmapViewOfFile(pb); return (0); //Выход из функции } //=== Реализация функций, вызываемых из LUA ====================================================================// // Получает строку Email информации и отправляет ее в C# static int forLua_SendEmail(lua_State *L) { //Если указатель на память получен if (hFileMapEmail) { // Получает доступ (представление) непосредственно к чтению/записи байт pb = (PBYTE)(MapViewOfFile(hFileMapEmail, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 4096)); // Если доступ получен if (pb != NULL) { lua_getglobal(L, "EmailResult"); //Находит в стеке Lua функцию по ее названию и помещает ее наверх стека int callbackRef = luaL_ref(L, LUA_REGISTRYINDEX); //Получает индекс функции в специальной внутренней таблице (реестре) Lua //Очищает память for (int i = 0; i < 4096; i++)pb[i] = '\0'; //Сообщает приложению C# о готовности отправить письмо memcpy(pb, "Q_READY", 7); //Ждет ответа от C# не более 3-х секунд // Получает время в миллисекундах, прошедших с запуска ОС unsigned long long TickCount = GetTickCount(); while (true) { //Проверяет ответ о готовности от C# (ответом является "_QW_") if (QluaWriteReady()) { break;//Выходит из цикла для отправки письма } else { //Проверяет задержку if (GetTickCount() - TickCount >= 3000) { //Очищает память for (int i = 0; i < 4096; i++)pb[i] = '\0'; //Сообщает о невозможности отправки lua_rawgeti(L, LUA_REGISTRYINDEX, callbackRef); // Достает функцию из реестра Lua по ранее полученному индексу и помещает в стек lua_pushstring(L, "ОШИБКА: Почтовый клиент не запущен !!!"); //Записывает в Lua-стек полученный результат lua_call(L, 1, 0); //Вызывает выбранную функцию в скрипте QLua, передавая в нее 1 параметр (L - стек, 1 - количество передаваемых параметров, 0 - количество возвращаемых значений)) return (0);//Выходит из функции } } Sleep(1); // Пауза 1 миллисекунда } // Считывает из Lua-стека параметры Email-информации и объединяет их в одну строку char EmailInfo[4096] = "EMAIL_INFO;"; strcat(EmailInfo, lua_tostring(L, 1)); //SMTP сервер strcat(EmailInfo, ";"); strcat(EmailInfo, lua_tostring(L, 2)); //Ваш логин strcat(EmailInfo, ";"); strcat(EmailInfo, lua_tostring(L, 3)); //Ваш пароль strcat(EmailInfo, ";"); strcat(EmailInfo, lua_tostring(L, 4)); //Email получателя strcat(EmailInfo, ";"); strcat(EmailInfo, lua_tostring(L, 5)); //Email отправителя strcat(EmailInfo, ";"); strcat(EmailInfo, lua_tostring(L, 6)); //Тема письма strcat(EmailInfo, ";"); strcat(EmailInfo, lua_tostring(L, 7)); //Текст письма if (lua_isstring(L, 8) && lua_tostring(L, 8) != "") // Если есть вложение (путь к файлу) { strcat(EmailInfo, ";"); strcat(EmailInfo, lua_tostring(L, 8)); //Путь к файлу вложения } int Size = 0; // Считает количество символов в строке for (int i = 0; i < 4096; i++) { if (EmailInfo[i] == 0)break; Size++; } memcpy(pb + 4, EmailInfo, Size);// Записывает строку в память, начиная со 5-го байта memcpy(pb, CR, 4);// Устанавливает константу "_CR_", сообщая тем самым, что память записана и ожидает чтения C# std::thread thr(WaitingEmailResult, L); //Запускает выполнение функции в отдельном потоке thr.detach(); //Отсоединяет созданный поток от основного, делая его "фоновым" } } return(0); } //=== Регистрация реализованных в dll функций, чтобы они стали "видимы" для Lua ================================// static struct luaL_reg ls_lib[] = { { "SendEmail", forLua_SendEmail }, { NULL, NULL } }; //=== Регистрация названия библиотеки, видимого в скрипте Lua ==================================================// extern "C" LUALIB_API int luaopen_SenderEmail(lua_State *L) { luaL_openlib(L, "SenderEmail", ls_lib, 0); return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | //Почтовый клиент 2015(c)QuikLuaCSharp.ru using System; using System.ComponentModel; using System.IO; using System.IO.MemoryMappedFiles; using System.Net; using System.Net.Mail; using System.Threading; using System.Windows.Forms; namespace Email { public partial class Form1 : Form { public static SmtpClient Client; // Выделенная именованная память public static MemoryMappedFile EmailMemory; // Объекты для чтения из памяти public static StreamReader SR_EmailMemory; // Объекты для записи в память public static StreamWriter SW_EmailMemory; //КОНСТАНТЫ СОСТОЯНИЯ ПАМЯТИ const string QR = "_QR_"; // Память ожидает чтения Qlua (Qlua Read) const string QW = "_QW_"; // Память ожидает записи Qlua (Qlua Write) const string CR = "_CR_"; // Память ожидает чтения C# (C# Read) const string CW = "_CW_"; // Память ожидает записи C# (C# Write) public static bool EmailRun = true; // Флаг работы приложения public static bool EmailSending = false; // Флаг, что идет отправка email public Form1() { InitializeComponent(); // Создаст, или подключится к уже созданной памяти с таким именем EmailMemory = MemoryMappedFile.CreateOrOpen("EmailMemory", 4096, MemoryMappedFileAccess.ReadWrite); // Создает потоки для чтения SR_EmailMemory = new StreamReader(EmailMemory.CreateViewStream(), System.Text.Encoding.Default); // Создает потоки для записи SW_EmailMemory = new StreamWriter(EmailMemory.CreateViewStream(), System.Text.Encoding.Default); // Запускает функцию, которая в отдельном потоке ждет команды от QLua на отправку email GettingEmailInfo(); } //Считывает информацию из памяти "EmailMemory" public string GetEmailInfo() { string EmailInfo = ""; //Ждет от DLL сообщения о готовности отправить email ("Q_READY") while(EmailRun) { // Встает в начало потока SR_EmailMemory.BaseStream.Seek(0, SeekOrigin.Begin); // Считывает все, что есть в памяти, обрезая нули и др. сервисные символы EmailInfo = SR_EmailMemory.ReadToEnd().Trim('\0', '\r', '\n'); // Если пришло сообщение о готовности, выходит из цикла для дальнейших действий if (EmailInfo == "Q_READY") break; Thread.Sleep(10); // Пауза в 10 миллисекунд, чтобы не перегружать процессор } if (!EmailRun) return ""; // Если приложение завершается, выходит из функции, чтобы не задерживать процесс // Встает в начало потока SW_EmailMemory.BaseStream.Seek(0, SeekOrigin.Begin); // Очищает память, заполняя "нулевыми байтами" for (int i = 0; i < 4096; i++) SW_EmailMemory.Write("\0"); // Очищает все буферы и вызывает запись всех данных буферов в основной поток SW_EmailMemory.Flush(); // Встает в начало потока SW_EmailMemory.BaseStream.Seek(0, SeekOrigin.Begin); // Записывает в начало константу "_QW_", означающую, что память ожидает записи QLua SW_EmailMemory.Write(QW); // Очищает все буферы и вызывает запись всех данных буферов в основной поток SW_EmailMemory.Flush(); // Выполняет цикл, пока память не готова для чтения C# while (EmailInfo.Length == 0 || EmailInfo.Length < 4 || (EmailInfo.Length >= 4 && EmailInfo.Substring(0, 4) != CR)) { // Встает в начало потока SR_EmailMemory.BaseStream.Seek(0, SeekOrigin.Begin); // Считывает все, что есть в памяти, обрезая нули и др. сервисные символы EmailInfo = SR_EmailMemory.ReadToEnd().Trim('\0', '\r', '\n'); Thread.Sleep(10); // Пауза в 10 миллисекунд, чтобы не перегружать процессор if (!EmailRun) return ""; // Если приложение завершается, выходит из функции, чтобы не задерживать процесс } if (!EmailRun) return ""; // Если приложение завершается, выходит из функции, чтобы не задерживать процесс // Встает в начало потока SW_EmailMemory.BaseStream.Seek(0, SeekOrigin.Begin); // Очищает память, заполняя "нулевыми байтами" for (int i = 0; i < 4096; i++) SW_EmailMemory.Write("\0"); // Очищает все буферы и вызывает запись всех данных буферов в основной поток SW_EmailMemory.Flush(); // Встает в начало потока SW_EmailMemory.BaseStream.Seek(0, SeekOrigin.Begin); // Записывает в начало константу "_CW_", означающую, что память ожидает записи C# SW_EmailMemory.Write(CW); // Очищает все буферы и вызывает запись всех данных буферов в основной поток SW_EmailMemory.Flush(); // Возвращает то, что прочитано, без управляющей константы return EmailInfo.Substring(4); } // Функция постоянно читает данные из памяти "EmailMemory" при помощи функции GetEmailInfo public void GettingEmailInfo() { //Запускает функцию получения сервисной информации в отдельном потоке, чтобы приложение откликалось на действия пользователя //Чтобы остановить выполнение данного потока, нужно переменной "EmailRun" присвоить значение "false" new Thread(() => // Создает новый поток { string EmailInfo = ""; string[] EmailInfoParts; //Постоянный цикл в отдельном потоке while (EmailRun) { if (EmailSending) {Thread.Sleep(1); continue; } // Если в данный момент выполняется отправка email-сообщения, то ждет завершения //Получает сервисную информацию из памяти, если ее нет, то ждет EmailInfo = GetEmailInfo(); // Разделяет полученную строку на элементы EmailInfoParts = EmailInfo.Split(';'); if (EmailInfoParts.Length > 1 && EmailInfoParts[0] == "EMAIL_INFO")// Если получены данные для отправки письма { //Отправляет письмо Send(EmailInfoParts); } //Чтобы процесс не "забивал" одно из ядер процессора на 100% нужна пауза в 10 миллисекунд Thread.Sleep(10); } }).Start(); // Запускает поток } // Отправляет email private void Send(string[] EmailInfoParts) { string Server = EmailInfoParts[1]; // Сервер string Login = EmailInfoParts[2]; // Логин string Password = EmailInfoParts[3]; // Пароль string To = EmailInfoParts[4]; // Кому string From = EmailInfoParts[5]; // От кого string Subject = EmailInfoParts[6]; // Тема string Body = EmailInfoParts[7]; // Текст письма string Attachment = (EmailInfoParts.Length == 9) ? EmailInfoParts[8] : ""; // Полный, или относительный путь к файлу вложения (если есть) EmailSending = true; // Устанавливает флаг, что началась отправка email, чтобы не инициировать новую try // Пытается выполнить блок кода { Client = new SmtpClient(Server); // Инициализирует новый экземпляр класса SmtpClient, который отправляет электронную почту с помощью указанного сервера SMTP MailAddress from = new MailAddress(From); // От кого MailAddress to = new MailAddress(To); // Кому MailMessage message = new MailMessage(from, to); // Содает объект сообщения message.Body = Body; // Добавляет к сообщению текст message.BodyEncoding = System.Text.Encoding.UTF8; // Устанавливает кодировку для текста сообщения message.Subject = Subject; // Добавляет к сообщению тему message.SubjectEncoding = System.Text.Encoding.UTF8; // Устанавливает кодировку для темы сообщения if (Attachment != "") // Если есть вложение (файл) { Attachment data = new Attachment(Attachment); // Создает объект вложения message.Attachments.Add(data); // Добавляет вложение к сообщению } // Инициализирует новый экземпляр класса NetworkCredential с заданными значениями пароля и имени пользователя Client.Credentials = new NetworkCredential(Login, Password); // Указывает, использует ли SmtpClient протокол SSL для шифрования подключения Client.EnableSsl = true; // Происходит после завершения асинхронной операции по отправке электронной почты (регистрирует функцию обратного вызова) Client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); // Отправляет указанное сообщение SMTP-серверу для доставки в качестве асинхронной операции Client.SendAsync(message, null); } catch (Exception ex) // Если при выполнении блока кода после try произошла ошибка { SetMemoryResult("Ошибка отправки email: " + ex.ToString()); // Записывает в память результат отправки email EmailSending = false; // Сбрасывает флаг (процесс отправки завершен) // Отправляет сообщение QUIT на SMTP-сервер, правильно завершает TCP-подключение и освобождает все ресурсы, используемые текущим экземпляром класса SmtpClient Client.Dispose(); } } //Функция записывает в память результат отправки email private static void SetMemoryResult(string Result) { string S = ""; // Ожидает в цикле разрешения на запись в память while (EmailRun) { // Встает в начало потока SR_EmailMemory.BaseStream.Seek(0, SeekOrigin.Begin); // Считывает все, что есть в памяти S = SR_EmailMemory.ReadToEnd(); // Если память ожидает записи C#, выходит из цикла while, иначе ждет 10 миллисекунд if (S.Length > 0 && S.Substring(0, 4) == CW) break; else Thread.Sleep(10); } // Встает в начало потока SW_EmailMemory.BaseStream.Seek(0, SeekOrigin.Begin); // Очищает память, заполняя "нулевыми байтами" for (int i = 0; i < 4096; i++) SW_EmailMemory.Write("\0"); // Очищает все буферы и вызывает запись всех данных буферов в основной поток SW_EmailMemory.Flush(); // Встает в начало потока SW_EmailMemory.BaseStream.Seek(0, SeekOrigin.Begin); // Записывает в начало константу "_QR_", означающую, что память ожидает чтения QLua и далее записывает саму команду SW_EmailMemory.Write(QR + Result); // Очищает все буферы и вызывает запись всех данных буферов в основной поток SW_EmailMemory.Flush(); } // Функция вызывается по окончанию асинхронной отправки почтового сообщения private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) { if (e.Error != null) // Если произошла ошибка { SetMemoryResult("Ошибка отправки email: " + e.Error.ToString()); // Записывает в память результат отправки email EmailSending = false; // Сбрасывает флаг (процесс отправки завершен) // Отправляет сообщение QUIT на SMTP-сервер, правильно завершает TCP-подключение и освобождает все ресурсы, используемые текущим экземпляром класса SmtpClient Client.Dispose(); } else // Отправка прошла без ошибок { SetMemoryResult("OK"); // Записывает в память результат отправки email EmailSending = false; // Сбрасывает флаг (процесс отправки завершен) // Отправляет сообщение QUIT на SMTP-сервер, правильно завершает TCP-подключение и освобождает все ресурсы, используемые текущим экземпляром класса SmtpClient Client.Dispose(); } } // Функция вызывается при закрытии данного приложения private void Form1_FormClosing(object sender, FormClosingEventArgs e) { notifyIcon1.Visible = false; // Не отображать иконку EmailRun = false; // Сбрасывает флаг работы приложения, чтобы завершился отдельный поток } // Функция вызывается при изменении размеров формы, следовательно, и при сворачивании и разворачивании private void Form1_Resize(object sender, EventArgs e) { if (WindowState == FormWindowState.Minimized) // Если форма свернута { Hide(); // Скрывает форму notifyIcon1.Visible = true; // Отображает иконку в области уведомлений } } // Функция вызывается при клике в контекстном меню, которое появляется при клике правой кнопкой мыши по иконке private void contextMenuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e) { if (e.ClickedItem.Text == "Закрыть") // Если клик по пункту "Закрыть" { Application.Exit(); // Закрывает приложение EmailRun = false; // Сбрасывает флаг работы приложения, чтобы завершился отдельный поток } } } } |
Если по какой-то причине Вы не можете, или не хотите, использовать Visual Studio 2015, то можете скачать готовое решение для Visual Studio 2010. Данное решение использует библиотеку "BOOST" для C/C++, если Вы не знаете как использовать данную библиотеку, можете ознакомиться здесь.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | private void button1_Click(object sender, EventArgs e) { string Server = "smtp.mail.ru"; int Port = 25; string Login = "test@mail.ru"; string Password = "MyPassword"; string To = "test@mail.ru"; // Кому string From = "test@mail.ru"; // От кого string Subject = "Тест SMTP C#"; // Тема string Body = "Тестовое сообщение"; // Текст письма // Инициализирует новый экземпляр класса SmtpClient, который отправляет электронную почту с помощью указанного сервера SMTP и порта SmtpClient Client = new SmtpClient(Server, Port); // Инициализирует новый экземпляр класса NetworkCredential с заданными значениями пароля и имени пользователя Client.Credentials = new NetworkCredential(Login, Password); // Указывает, использует ли SmtpClient протокол SSL для шифрования подключения Client.EnableSsl = true; // Происходит после завершения асинхронной операции по отправке электронной почты (регистрирует функцию обратного вызова) Client.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback); // Отправляет указанное сообщение SMTP-серверу для доставки в качестве асинхронной операции. //Отправитель, получатели, тема и основная часть сообщения указываются с помощью объектов String Client.SendMailAsync(From, To, Subject, Body); // Отправляет сообщение QUIT на SMTP-сервер, правильно завершает TCP-подключение и освобождает все ресурсы, используемые текущим экземпляром класса SmtpClient Client.Dispose(); } // Функция вызывается по окончанию асинхронной отправки почтового сообщения private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e) { if (e.Error != null) { MessageBox.Show("Ошибка отправки email: " + e.Error.ToString()); } else { MessageBox.Show("Сообщение email успешно отправлено!"); } } |
Некоторые почтовые сервисы предоставляют оповещение по SMS о новых письмах, по этому, этот способ можно использовать как альтернативное оповещение.
Если у Вас появились какие-то вопросы, задайте их в комментариях под статьей !!!
Простите, а где файл EMail.exe?
Что-то я не вижу его на этой странице...
И еще: вы не могли бы сделать сборку архива lua_mime_socket.zip для Quik8 под Win64? Тот, который здесь присутствует, похоже, сделан для Win32...
Вот здесь Email.exe

Изображение:
Большое спасибо, Дмитрий.
Но мне было бы гораздо важнее, чтобы сработала отсылка СМС из QLua-скрипта. А с этим что-то не получается в Quik8 под Win64. Ощущение, что библиотеки собраны под Win32
Имеется ли у вас сборка lua_mime_socket.zip для Quik8 под Win64?
...и по поводу EmailSender - опять не получается, сразу после исполнения инструкции
require("SenderEmail");
возникает ошибка
error loading module 'SenderEmail' from file '.\SenderEmail.dll':
%1 не является приложением Win32.
Там красным текстом в статье написано что нужно использовать другую dll для x64 и называется она по другому, нужно в Lua скрипте тоже прописать SenderEmail_x64 вместо SenderEmail
Виноват, исправился.
Сейчас в каталоге C:\BCS_Work\QUIK_BCS лежит SenderEmail_x64.dll
package.cpath выглядит так: .\?.dll;C:\BCS_Work\QUIK_BCS\?.dll;C:\BCS_Work\QUIK_BCS\loadall.dll;C:\BCS_Work\QUIK_BCS\Include\?.dll;C:\BCS_Work\QUIK_BCS\LuaIndicators\?.dll
Но на инструкцию
require("SenderEmail_x64");
возникает диагностика
error loading module 'SenderEmail_x64' from file '.\SenderEmail_x64.dll':
Не найден указанный модуль.
Просто положите SenderEmail_x64.dll в корневой каталог терминала, в ту же папку где info.exe и запустите вот такой скрипт с одной строкой без всяких package.cpath:
Именно так я и сделал. Вот весь мой скрипт:
function main()
require("SenderEmail_x64")
end;
...на который я получаю сообщение
error loading module 'SenderEmail_x64' from file 'C:\BCS_Work\QUIK_BCS\SenderEmail_x64.dll':
Не найден указанный модуль.
Какая у Вас версия ОС ?
Windows 10 Pro, x64
lua_mime_socket это папки из Гугловской LuaForWindows, я их не собирал сам.
При желании можно отправлять СМС через приложение C#, а в него слать инфу через dll коннектор обычный, примеры сборки и использования которых описаны на сайте.
Могу Вам скинуть решение под Visual Studio 2019 Community, соберете dll у себя на компьютере. У меня тоже 10 x64 и все работает, не знаю почему 🙂
А могли бы вы скинуть решение для Visual Studio 2019 Community, но не для SenderEmail_x64, а для lua_mime_socket?
Мне гораздо нужнее оповещения по СМС, чем по е-мейлу.
Поздно увидел ваш ответ по поводу lua_mime_socket. Хорошо, если можно, скиньте решение для SenderEmail_x64 под Visual Studio 2019 Community
https://1drv.ms/u/s!AsAAhw-6vq0mifJsarB2qzrtu982rg?e=Edfdf9
Спасибо, Дмитрий.
Всегда пожалуйста 🙂
я там вам статеечку наваял, может опубликуете?
Прошу прощения, не увидел сразу, благодарю, опубликовал.
У меня нет сборки данных библиотек под x64, это были папки из устанавливаемой LuaForWindows, но ее нет, как я понял, под x64. Задачу решить, конечно, можно, но сейчас нет времени в этом копаться.
Здравствуйте. Можете для 8 квика библиотеку SenderEmail.dll собрать?
Здравствуйте, пожалуйста: https://quikluacsharp.ru/wp-content/uploads/2019/12/SenderEmail_x64.zip 🙂
Отлично! Спасибо!

...
Сначала обрадовался. А потом попробовал запустить... (
Ссылка на скриншот результата и тестовый код.
Изображение:
Сообщение квика: "error loading module 'SenderEmail_x64' from file 'C:\QUIK-Junior8\SenderEmail_x64.dll':
Не найден указанный модуль."
Lua код:
Если картинку скриншота не видно, ссылка (без пробелов):
http: //prntscr. com/q4oyo2
У Вас какая версия ОС ? Библиотека собрана под Win 10 x64
Windows Server 2016 Standart x64
Выше вижу решение для студии 2019 уже скинули. Скачаю, сам попробую собрать.
Интересно, а на другом компьютере у кого-нибудь подключается нормально эта библиотека?..
Пробовал кто-нибудь?
Собрал сам в 19 студии. Заработало.
Здравствуйте, пользуется кто на 8ке? Работает? Не хочется снова искать решения уведомлений!
Здравствуйте, скажите как можно запустить отправку по почте из двух квиков на одном компьютере?
Здравствуйте, мне кажется не должно быть никаких проблем, в каждом квике свой скрипт работает и все хорошо.
Увы нет, где-то они пересекаются. Запущенный последним вылетает.
Понял, нужно имена памяти разные сделать и приложения 2 разных создать.
У меня судия 17, на сайте сборка 15. Я могу это сделать в 17? И хотелось-бы по подробнее если можно...пожалуйста!!!
На 17-й можете сделать, по поводу поподробнее, нет, к сожалению, времени рассказывать, в двух словах, там используется именованная память (MemoryMappedFile) для обмена данными между Lua и C#, приложение C# заточено сейчас на одну связь, одно имя памяти, нужно сделать 2, для каждого терминала свой канал. Если не сможете разобраться, обращайтесь, наши программисты сделают быстро и за адекватные деньги.
Спасибо большое. С такими подсказками получилось. Память переименовать много ума не надо) А файл email.exe надо в каждом квике запускать. Как происходит поиск почтового клиента? Я вчера в одну папку квика не скопировал а сообщение пришло dllка была.
Всегда пожалуйста) Как происходит поиск не помню уже, по моему просто в своей памяти сообщения ждет кто-то.
Или в одном приложении обе памяти мониторить
const char *QR = "_QR_"; // Память ожидает чтения Qlua (Qlua Read)
const char *QW = "_QW_"; // Память ожидает записи Qlua (Qlua Write)
const char *CR = "_CR_"; // Память ожидает чтения C# (C# Read)
const char *CW = "_CW_"; // Память ожидает записи C# (C# Write) -это? Можно просто добавить двоечки const char *QR2 = "_QR2_"; // Память ожидает чтения Qlua (Qlua Read)
Нет 🙂 Эти константы не нужно трогать.
Пока никто ничего не спрашивает, спрошу))) Хотелось бы знать, память она только при сохранении конфликтует. Мы пытаемся записать а там уже есть? Поэтому же имя разное задаем. Можно тогда проверять перед сохранением? Или мы при загрузки(начале работы) приложения как бы память резервируем и даем имя? Как происходит взаимодействие связки?
Не совсем понял вопрос, но память мы на старте выделяем и именуем.
Ответ правильный) В смысле правильно поняли вопрос))) Смотрю дллки от 8 го квика отваливаются, автозапуск квика. Уведомление, он же на 32, тоже не будет работать? ...И сейчас через какое то время работы, несколько отправок сообщений. Выходит сообщение. Почтовый клиент не запущен. Хотя он запущен и сообщение отправил при этой ошибке. Я только тестирую. Еще не разбирался. Стоит условие отправлять при условии"OK". Соответственно он больше не отправляет. Если условие поменять должен работать.Но надо наверное найти почему приходит ошибка. Было у кого такое?
Я с 8 вообще еще не сталкивался
Здравствуйте, настроил все по примеру отправки EMAIL на ящик MAIL.RU из QLua, но в теле письма нет сообщения о конкретном событии из квик, только строка "Текст письма".
Добрый день! По Вашей схеме давно и безотказно работают смс-уведомления. Сейчас по этой же схеме пытаюсь сделать уведомления через телеграмм. Казалось бы и в том и другом случае отправляется http запрос, только при отправке на телеграмм квик выдает:
301 Moved Permanently 301 Moved Permanently nginx/1.12.2
Подскажите где копать. Сразу скажу, что не программист, но луа-скрипт писал самомтоятельно.
Спасибо.
Не все вставилось, дополняю
" 301 Moved Permanently 301 Moved Permanently nginx/1.12.2 "
Здравствуйте! Копайте в сторону кодов ошибок сервера, 301 это код ошибки. Как я понимаю, это сервер телеграмма выдал ошибку на Ваш http запрос.
Думаю да, вижу это в сообщениях квика после отправки запроса. Копал уже в эту сторону, только уперся, т.к. не программист.
Добрый день!
Подскажите, как применить ваш код, для оповещения по параметру?, то есть я задал оповещение по параметру, что бы например - USD_RUB >=60, и когда данное условия сработало, мне на Email приходило сообщение, о данном событии. С Админами на работе договорился, они разрешили мне Quik поставить на севере, который всегда включён.
Добрый день! Вы знакомы с программированием?
нет не знаком, как я понял как есть ваш код не сработает, для моей задачи, верно я понимаю?
Да, верно. Нужно получать цену инструмента, сравнивать ее со значением, и если условие сработало, отправлять письмо, причем, нужно еще учесть возможность срабатывания условия несколько раз за день и т.п. Ничего сложного нет, но всю эту логику нужно прописать.
По идее, если Вам интересно, то можете сами все это прописать:
здесь есть функция getParamEx https://quikluacsharp.ru/?p=258, которой можно получить последнюю цену инструмента из таблицы текущие торги, а в разделе меню "QLua(Lua) основы" можете посмотреть какие конструкции языка используются для объяснения логики компьютеру (переменные, условные элементы, циклы)
Дмитрий, здравствуйте!
Много полезностей нашел у Вас. К этой статье предлагаю альтернативу - отправка сообщений в Telegram. Набросал небольшого бота, найти можно в Telegram как @QUIKTeleBot.
Спасибо!
Здравствуйте! Вам спасибо, пригодится!
Всем удачных бестолковых выходных!
Допилил вторую версию. Теперь с коллбэком - можно из Телеграма писать КВИКу. Новый бот - @QUIKMessagingBot
Привет!
viber://pa?chatURI=quikmessenger - теперь и в Вайбере
icebird, смог отправлять из qlua в telegram, а вот viber бота не нашел, он работает сейчас? А как отправлять сообщения из C# в телеграмм бот, нет ли такого же простого примера как для lua?
Здравствуйте! С вайбером загвоздка - сам вайбер не спешит делать чат публичным, хотя бот в нем работает сейчас (только что проверил). Попробуйте открыть ссылка viber://pa?chatURI=quikmessenger из самого вайбера (отправив ее себе, например). Про C# - нет, извините.
Приветствую! А нельзя ли поподробней: где, что, как? Очень интересно. Спасибо!
Здравствуйте!
Ссылка на длл-ку и пример qlua-кода есть в самом Telegram - найдите в мессенджере @QUIKTeleBot.
Вы умудрились все lua стандартные скрипты по ssl, json + dll-ки обьединить в 1 dll. Или вообще полностью все нужные функции переписали?
Александр, по-честному - все намного проще 🙂 ДЛЛ-ка жирноватая - т. к. скомпилирована на Delphi Seattle и при этом в пятницу вечером под пивас. На будущее в планах есть организация коллбэков (например, понадобится закрывать позы из телеграма, находясь за рулем). Но - на будущее... Пока занят другим проектом.
Я тоже делал в свободное время, часть lua файлов обьединил в 1 lua, но в dll-ки типа core.dll не лез.
У меня осталось, что требуется:
которые тянут свои по цепочке. Если вы всю эту кучу смогли обьединить в 1 файл, то молодцы.
Из функций там надо:
bot.sendMessage(Идентификатор получателя, Сообщение)
bot.getUpdates(номер)
Ваша Dll обе эти функции обеспечивает?
Только одна функция - SendMessage("Пользователь","Сообщение")
А getUpdates что должна делать?
Пожалуйста напишите мне на luarobot@yandex.ru есть идеи, мне есть что предложить 🙂
Пожалуйста напишите мне на masalexven yandex.ru есть идеи, мне есть что предложить
getUpdates получает команды от робота телеграмма и передает коллекцию в lua-скрипт для разбора. Собственно по ней и идет обратная связь от робота к скрипту.
Отписался. По поводу getUpdates - ее из main в цикле вызывать? Не проще из самой для-ки коллбэк луа-скрипта вызвать и передать туда сообщение?
Это уже вопрос реализации, я использовал стандартные наработки, которые есть в Интернете по связке телеграмма и lua, там эта функция отвечает за опрос робота телеграмма и выдачу коллекции с кучей информации. Она вызывается из main().
В стандартные колбеки много кода нельзя делать, поскольку они в основном потоке QUIK, лучше максимум обработки делать через main().
У Дмитрия есть информация на тему потоков и колбеков на данном ресурсе.
Дмитрий доброго дня.
Я не волшебник но хочется выучиться на него.
Помогите понять почему не работает отсылка СМС.
1 http = require('socket.http');
2 login = "cann"; -- Ваш логин на сайте smsc.ru
3 password = "pa1959pa"; -- Ваш пароль на сайте smsc.ru
4 phone = "79190655741"; -- Ваш номер телефона
5 message = "робот";
6 function main()
7 message(tostring(http.request "http://smsc.ru/sys/send.php?login="..login.."&psw="..password.."&phones="..phone.."&mes="..message));
8 end;
При запуске данного кода в квик пишет такую ошибку
lua:7:attempt to call global 'message'(a string value)
Предварительно программы "lua", "mime", "socket" установлены деньги на сервере СМС есть.
Просветите в чем проблема.
Здравствуйте! В статье была ошибка в коде, исправил, прошу прощения! В Qlua есть встроенная функция message, которая выводит сообщения, а я ее подменил строкой, вот Quik и ругался у Вас.
Дмитрий доброго и удачного Вам дня.
Исправил код но опять возникла непонятка.
При запуске выдает ;
ERROR = 1 (parameters error)cann&psw=pa1959pa&phones=79190655741&mes=робот
мои данные в коде
http = require('socket.http');
login = "cann"; -- Ваш логин на сайте smsc.ru
password = "pa1959pa"; -- Ваш пароль на сайте smsc.ru
phone = "79190655741"; -- Ваш номер телефона
msg = "робот";
function main()
message(tostring(http.request "http://smsc.ru/sys/send.php?login="..login.."&psw="..password.."&phones="..phone.."&mes="..msg));
end;
в чем проблема.
Здравствуйте! Попробуйте в тексте сообщения (msg) использовать только английские буквы, например, robot, возможно проблема в неверной кодировке скрипта и русские символы неправильно передаются.
По русски и по английски и цифры пробовал - не работает, такую же ошибку выдает, что делать?
ERROR = 1 (parameters error)XXX&psw=XXX&phones=XXX&mes=SMS
Вместо XXX - нормальный данные
Нашел причину!
так не работало:
а так работает:
"Найди 2 отличия и получи приз" 🙂
Скобки - приз давай
Приз это работающие смс, получите, распишитесь 🙂
Получили, расписались
🙂
Добрый день!
А можно функцию SenderEmail.SendEmail как-то вызывать несколько раз в скрипте? Просто первый раз письмо отправляется, а при втором вызове- ОШИБКА: Почтовый клиент не запущен !!
Добавила sleep (3100) после отправки каждого email, в этом случае работает. Я правильно понимаю, что из-за этой части кода невозможно отправлять письма ранее этого времени?
if (GetTickCount() - TickCount >= 3000)
{
//Очищает память
for (int i = 0; i < 4096; i++)pb[i] = '\0';
//Сообщает о невозможности отправки
lua_rawgeti(L, LUA_REGISTRYINDEX, callbackRef); // Достает функцию из реестра Lua по ранее полученному индексу и помещает в стек
lua_pushstring(L, "ОШИБКА: Почтовый клиент не запущен !!!"); //Записывает в Lua-стек полученный результат
lua_call(L, 1, 0); //Вызывает выбранную функцию в скрипте QLua, передавая в нее 1 параметр (L - стек, 1 - количество передаваемых параметров, 0 - количество возвращаемых значений))
return (0);//Выходит из функции
}
}
Хотя при добавлении в функцию реплая
function EmailResult(res)
message(res);
while res~="OK" do sleep(1) end
end;
Все равно отправляется только первое письмо..
Здравствуйте! Эта часть кода
ждет время только если нет ответа от C# о том, что он готов отправить письмо, если ответ пришел, то
будет истиной и цикл while будет завершен, код перейдет дальше к процессу отправки письма.
Вам просто нужно после отправки письма дождаться результата в функции EmailResult, как только он придет, можете сразу отправлять новое письмо.
-----Вам просто нужно после отправки письма дождаться результата в функции EmailResult, как только он придет, можете сразу отправлять новое письмо.
А разве строчка
while res~="OK" do sleep(1) end
в функции
function EmailResult(res)
message(res);
while res~="OK" do sleep(1) end
end;
этим не является?
Нет, функция EmailResult вызывается по результату отправки, в нее в переменную res передается результат "ОК", или текст ошибки. Если письмо отправлено, то в функцию передастся "ОК" и Ваша строка не отработает ни одного цикла, а если передастся текст ошибки, то скрипт просто зависнет в этой функции, т.к. никогда не дождется следующего результата, потому что письмо отправляется не внутри этой функции, а в dll и С#
Вот Вам простой пример:
Спасибо, поняла, что вариант нерабочий. Но как тогда можно отследить?
Попробовала так, писем отправляется уже больше:) но все равно на третьем опять та же ошибка
function emaily(tema, tekst)
resm=nil
SenderEmail.SendEmail(
"smtp.mail.ru",
"mail@mail.ru",
"1234",
"mail@mail.ru",
"mail@mail.ru",
tema,
tekst)
while resm==nil do sleep(1) end
end
function EmailResult(res)
message(res)
resm=res
end;
Даже не знаю, вроде бы все правильно делаете, нужно отлаживать связку DLL - C#, смотреть что в памяти, у меня нет сейчас времени, к сожалению, этим заниматься.
Здравствуйте,
если smtp сервер не мэйловский, Email.exe и библиотека ведь должны работать?
Возникает ошибка
Ошибка отправки email: System.Net.Mail.SmtpException: Failure sending mail. ---> System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.
at System.Net.Mail.SmtpConnection.ConnectAndHandshakeAsyncResult.End(IAsyncResult result)
at System.Net.Mail.SmtpTransport.EndGetConnection(IAsyncResult result)
at System.Net.Mail.SmtpClient.ConnectCallback(IAsyncResult result)
--- End of inner exception stack trace ---
Здравствуйте, не с любой почтой работает. Пробовали на mail.ru ?
Там с шифрованием проблемы.
Как раз не mail, а smtp своего домена..
Я понял, имел в виду попробуйте на mail отправить, может быть вообще, в принципе, не работает.
Через mail.ru работает
Т.е. дело в exe файле?
Да, в нем, я как-то давно тоже не мог на какой-то почтовый сервис письмо отправить таким способом, тоже на шифрование ругался, пару вечером покопался, так и не смог найти решение, возможно Вам больше повезет 🙂
На mail используется ssl, на моем домене-нет, поэтому после замены строки в коде экзешника
Client.EnableSsl = true;
на
Client.EnableSsl = false;
все заработало.
Спасибо.
Вам повезло, поздравляю 🙂 В моем случае на сервере тоже был ssl, но они были несовместимы.