Is there a way to temporarily override Moodle's SMTP settings in a custom PHP script? - smtp

For reasons too complex to disclose here, a client of mine has requested that we develop a custom notifications script (installed under the Moodle root as a plain .php script) that runs on a cron and scans certain activities in Moodle (3.11) in order to send notifications to students (but only in one specific course) when other students are posting/participating in those other activities.
My complication comes in when trying to send emails in this notifications script using Moodle's internal mailing system, which I understand is a custom implementation of PHPMailer. The client wants the emails sent by this script to come through a different email address than the official one used by the rest of the Moodle site. So, while all regular Moodle emails (password resets, etc.) should come from "original#example.com", they want the custom emails in this script to come from "new#example.com" instead.
Example:
// prepare variables
$subject = "subject line";
$body = "some body text";
$toUser = $DB->get_record('user', array('email' => 'somestudent#example.com'));
$fromUser = $DB->get_record('user', array('email' => 'new#example.com'));
// TO DO: swap out Moodle SMTP settings - if possible?
// send email
$success = email_to_user($toUser, $fromUser, $subject, '', $body);
I am currently using the email_to_user() method in Moodle but, by changing the "from user" value (as shown above), can only change the "name" of the sender, not the email address it actually sends from. So, the result is an email with sender/header info that looks like "Custom User (via Moodle Site) original#example.com" rather than the default which is essentially "Moodle Site original#example.com".
What I actually want to appear is "Custom User new#example.com". To do this, I understand that I would need to swap out the SMTP settings prior to sending.
Is there a way to temporarily use different SMTP settings in Moodle, without overwriting the ones in the database?
If not, is there some other way or repurposing Moodle's existing PHPMailer to send emails using manual SMTP credentials - such as creating a new instance of PHPMailer using the same code packaged within Moodle by in which I can specify custom SMTP settings?

After digging through the files in Moodle's messaging and core libraries, as well as the PHPMailer docs, I came up with the following solution. This still piggybacks off of Moodle's internal mail system (PHPMailer), but is a much more direct way of creating a PHPMailer instance. Because this bypasses a lot of Moodle's additional functions, I was not able to call email_to_user() and this required manually configuring a lot of settings that Moodle would normally take care of. But, in the end, I am able to send email from the script under my Moodle webroot directory without having to install, configure, or maintain a separate mail sending library (i.e. a separate version of PHPMailer).
// create ne PHPMailer instance and configure as needed
$mail = get_mailer();
$mail->Sender = 'new#example.com';
$mail->Host = "smtp.host.com";
$mail->Port = "587";
$mail->IsSMTP();
$mail->SMTPSecure = "tls";
$mail->SMTPAuth = true;
$mail->setLanguage("en");
$mail->SetFrom("new#example.com","New Name");
$mail->Username = "new#example.com";
$mail->Password = "password";
$mail->AuthType = "Login";
$mail->IsHTML(true);
For each email that needs to go out, I then just call a few functions to update the required parameters.
// clear existing recipient list before forming new email
$mail->ClearAllRecipients();
// form new email by specifying only basic attributes
$mail->Subject = "Email Subject Line";
$mail->Body = "This is a new text body.";
// address directly to student's email
$mail->addAddress('recipient#example.com');
// send email
$success = $mail->send();

Related

SSIS Send Mail Task Failed

The following is the error i get when i execute a simple package containing send mail task. i have configured the SMTP connection manager with server-smtp.office365.com and checked the windows authentication and ssl options too.
Thanks
Error: 0xC002F304 at Send Mail Task, Send Mail Task: An error occurred
with the following error message: "The SMTP server requires a secure
connection or the client was not authenticated. The server response
was: 5.7.57 SMTP; Client was not authenticated to send anonymous mail
during MAIL FROM [BMXPR01CA0031.INDPRD01.PROD.OUTLOOK.COM]".
This is a known issue. Check out this msdn link. It states the following in answer:
The SMTP Task in SSIS only supports Windows Authentication and the
port number cannot be changed. For a SMTP server that uses non-Windows
Authentication, we can use SmtpClient Class in Script Task to send the
email
That's why sending email via office365 fails.
In order to work with office365, either you can look for third party plugins integration with SSIS or you can use script task like below:
using System.Net.Mail;
using System.Net;
.
.
.
public void Main()
{
MailMessage mail = new MailMessage("<from email address>", "<to email address>");
mail.Body = "ssis sample email body";
mail.Subject = "ssis sample email subject";
//mail.Attachments.Add(new Attachment(AttachmentDiscardContratti));
//mail.Attachments.Add(new Attachment(AttachmentDiscardOrdini));
SmtpClient client = new SmtpClient("smtp.office365.com", 587);
client.EnableSsl = true;
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential("<login email>", "<login password>");
client.Send(mail);
Dts.TaskResult = (int)ScriptResults.Success;
}
ps: swap and as I am not sure which one comes first.
another sample of code is available in this SO answer (not tested by me)
this can easly be achieved using execute sql task. first create a stored procedure and execute sp_send_dbmail in your newly created procedure. this sp requires many parameters .. pass the values of these parameters from ssis and u will be good. please search more on google about this procedure . u can even send attachments on this procedure

ewsExchangeAPI Send Email Performance Issue

We planned to migrate the Old Outlook MAPI Logic to EWS Exchange API to send email. I have tested the performance of sending email by triggering 1500 emails (looped) with the attachment of 256 kb PDF File.
For One email it is taking 5 to 6 seconds and overall it is taking 2 hours to send all 1500 emails.
But in other side using Outlook MAPI just taking 45 Minutes to send all 1500 emails.
Am just using basic send email method not much logic added as like below (not an actual code I used).
//Create the email message.
EmailMessage message = new EmailMessage(service);
message.Subject = "Message with Attachments";
message.Body = "This message contains one item attachment.";
message.ToRecipients.Add(UserData.EmailAddress);
//Create another item and use it as an attachment.
ItemAttachment<EmailMessage> itemAttachment1 = message.Attachments.AddItemAttachment<EmailMessage>();
itemAttachment1.Name = "Attached Message Item";
itemAttachment1.Item.Subject = "Message Item Subject";
itemAttachment1.Item.Body = "Message Item Body";
itemAttachment1.Item.ToRecipients.Add(UserData.EmailAddress);
message.SendAndSaveCopy();
Is this the API performance or I need to do some logic to send the email even faster.. Please suggest..
Thanks,
Gunasekaran Sambandhan
Sorry All,
There was a problem in my code. I just modified the way of call from consuming application, as well as a slight change in my .NET COM INTERFACE LIBRARY.
In my case VB 6.0 is the consuming Application.
.NET COM INTERFACE LIBRARY
I just modified the class representation in a way that:
Create Exchange Web service instance method
Send email
From VB 6.0 Application:
Call The Create Exchange Web service instance method
loop thru 1500 emails & call Send email with details
Just a basic discipline that has to be followed but I didn't so I got performance issue. Now I rectified myself & now it is working better that Outlook MAPI. (i.e. Now EWS Only takes 15 minutes)
Thanks,
Gunasekaran Sambandhan

PHP: view unsuccessful emails

I'm trying to figure out how to display a list of unsuccessful emails sent and a way to test it out.
I can display a list of the emails that were sent, but I'm unsure on how to retrieve the list of emails that were unsuccessfully sent out.
Here is what I'm using to retrieve it from the mysqldb:
//get the email address list
$query = "SELECT email FROM users
WHERE id IN (SELECT participant_id FROM roster AS ur WHERE ur.roster_id=".$roster['roster_id'].")";
$result = mysql_query($query);
$emailstring2 = "";
$email2 = $result;
while ($row = mysql_fetch_object($email2)){
$emailstring2 .= $row->email. "\n ";
}
In the message section, I retrieve it via:
$message .="Successful emails: \n".$emailstring2." \r\n";
How would I achieve this?
One keyword will get you the ones not sent: NOT
WHERE id NOT IN
You can't do this from PHP in a simple manner like this.
Think of it as a letter going through the postal service. All you can do is give the letter to the postman and hope that it reaches its destination. The postman will not come back and tell you if delivery was successful, or if the letter was actually read by the recipient. PHP's mail() function (and its derivatives) return TRUE to indicate that the message was accepted for delivery attempts, not that it was successfully delivered. (Delivery may not happen for hours or days.)
As a result, the best you can do is approximate delivery notification. There are a few ways you can do this:
Use a tracking pixel in the email that gets pinged when the user
opens the message. However, given that most email clients nowadays
default to "do not show images," I think this technique is rather
unreliable.
Send each message with a bounce address unique to the recipient. If
the message can't be delivered, it will return to the custom address
-- and that return message can be used to indicate that the original recipient's email address is no good. This is probably the most accurate method but is not simple to configure.
Use return receipts. Like tracking pixels, I think most email clients
default to never send these, so this is likely unreliable as well.
Use delivery status notification. This will require using a server
that supports it and sending to a server that supports it.
Send your mails through a service that will do this sort of tracking for you. (E.g. MailChimp or Constant Contact)

How to setup an SMS alert to website owner when a customer fills in a form?

Been doing some research on how to setup an SMS alert straight to the website owner's (our customer) phone when a website visitor fills in a form on his website. Obviously we're happy to sign up to a provider and pay a few cents for each message - not expecting this to be a freebie service.
A lot of the google results you get for this deal with bulk texting out to the many recipients which isn't what we're looking at here.
So what's the simplest small-scale way to achieve this via HTML and simple scripting?
This daniweb forum post offers clear and simple instructions using Coldfusion and that's fine but as it's 7 years old we wonder if things have moved on and are there better suggestions?
We'd be happy to script it very simply through ASP.NET or PHP or something else, but hoping to keep it lightweight, since this is a very simple website belonging to a small business.
I am working on a similar thing for my company.
We use a GSM modem such as: ZTE MF668A
It is a USB adapter which you can insert a SIM card into.
We purchased an SMS only plan, which is like $15 a month and you can send unlimited SMS. However the set up might be a bit more complicated than just using a bulk SMS service.
You can set up Diafaan SMS Server (http://www.diafaan.com/) on the computer with the GSM Modem to accept emails for a particular domain. (e.g. ours is #sms.com). Our exchange server forwards email to the Diafan Server. Diafaan will take the email and convert it to an SMS and send it using the GSM modem.
In you php code, you can use PHPMailer (http://phpmailer.worxware.com/) to construct an email and set the mail to address to be #sms.com.
You use it something like this:
ini_set("sendmail_from","user#company.com");
ini_set("SMTP","smtp.company.com");
require("PHPMailer/class.phpmailer.php");
$mail = new PHPMailer();
$mail->IsSMTP(); // set mailer to use SMTP
$mail->Host = "smtp.company.com"; // specify main and backup server
$mail->SMTPAuth = false; // turn on SMTP authentication
//$mail->Username = "name"; // SMTP username
//$mail->Password = "password"; // SMTP password
$mail->From = "user#company.com";
$mail->FromName = $salesPerson;
$mail->AddAddress("user2#company.com", "Pricing");
$mail->AddReplyTo("user#company.com", "User2");
$mail->AddBcc($salesPersonEmail, $salesPerson);
$mail->WordWrap = 50; // set word wrap to 50 characters
$mail->IsHTML(true); // set email format to HTML
$mail->Subject = $subject;
$mail->Body = $body;
if(!$mail->Send())
{
echo "Message could not be sent. <p>";
echo "Mailer Error: " . $mail->ErrorInfo;
exit;
}
There are also companies that offer SMS services such as PCSMS where you get 100 SMS per month for a fee. Then you just construct an email and send it to #pcsms.com.au. This is probably the easiest way to do it and is the way we used to do it, but the way we do it now is much cheaper.
Disclaimer, I do developer evangelism part time at Nexmo.
While you can setup a GSM modem to send SMS messages, it's likely easier (and depending on your usage, cheaper) to use a SMS API. Here are a few providers - pricing is in cents per message (depends on the API and destination, but hovers around a cent or two). You may be required to provision a virtual number - pricing there is generally dollars/month (again, depends on API and destination, hovers around a dollar or two).
Nexmo
Twilio
Tropo
If you're sending internationally, I think your best would be Nexmo. Or if you see any need to accept incoming messages in the future, Nexmo's pricing model will help you there.
All three APIs are straight forward REST/HTTP APIs - as long as whatever language you're using server side can make a web request, you should be able to send an SMS.
Eventually we used Esendex. Good support from them, decent code samples and plenty of mileage in the free trial (which in fact they were happy to extend when we asked).

How can I let users register my product online?

I've a MySql database hosted in my web site, with a table named UsrLic
Where any one wants to buy my software must register and enter his/her Generated Machine Key (+ username, email ...etc).
So my question is:
I want to automate this process from my software, how this Process will be?
Should I connect and update my database directly from my software ( and this means I must save all my database connection parameters in it * my database username , password , server * and then use ADO or MyDac to connect to this database ? and if yes how secure is this process ?
or any other suggestions .
I recommend creating an API on your web site in PHP and calling the API from Delphi.
That way, the database is only available to your web server and not to the client application, ever. In fact, you should run your database on localhost or with a private IP so that only machines on the same physical network can reach it.
I have implemented this and am implementing it again as we speak.
PHP
Create a new file named register_config.php. In this file, setup your MySQL connection information.
Create a file named register.php. In this file, put your registration functions. From this file, include 'register_config.php'. You will pass parameters to the functions you create here, and they will do the reading and writing to your database.
Create a file named register_api.php. From this file, include 'register.php'. Here, you will process POST or GET variables that are sent from your client application, call functions in register.php, and return results back to the client, all via HTTP.
You will have to research connecting to and querying a MySQL database. The W3Schools tutorials will have you doing this very quickly.
For example:
Your Delphi program calls https://mysite/register_api.php with Post() and sends the following values:
name=Marcus
email=marcus#gmail.com
Here's how the beginning of register_api.php might look:
// Our actual database and registration functions are in this library
include 'register.php';
// These are the name value pairs sent via POST from the client
$name = $_POST['name'];
$email = $_POST['email'];
// Sanitize and validate the input here...
// Register them in the DB by calling my function in register.php
if registerBuyer($name, $email) {
// Let them know we succeeded
echo "OK";
} else {
// Let them know we failed
echo "ERROR";
}
Delphi
Use Indy's TIdHTTP component and its Post() or Get() method to post data to register_api.php on the website.
You will get the response back in text from your API.
Keep it simple.
Security
All validation should be done on the server (API). The server must be the gatekeeper.
Sanitize all input to the API from the user (the client) before you call any functions, especially queries.
If you are using shared web hosting, make sure that register.php and register_config.php are not world readable.
If you are passing sensitive information, and it sounds like you are, you should call the registration API function from Delphi over HTTPS. HTTPS provides end to end protection so that nobody can sniff the data being sent off the wire.
Simply hookup a TIdSSLIOHandlerSocketOpenSSL component to your TIdHTTP component, and you're good to go, minus any certificate verification.
Use the SSL component's OnVerifyPeer event to write your own certificate verification method. This is important. If you don't verify the server side certificate, other sites can impersonate you with DNS poisoning and collect the data from your users instead of you. Though this is important, don't let this hold you up since it requires a bit more understanding. Add this in a future version.
Why don't you use e.g. share*it? They also handle the buying process (i don't see how you would do this for yourself..) and let you create a reg key through a delphi app.