Email using cron and including attachment to email from moodle - php

I would like to send emails only to users that have completed a specific course and add a pdf file (a certificate for completing the course) as attachment to the email, and do so at a specific time using moodle cron.
I have looked at some plugins to find out how it's done, but I'm still not sure how exactly I should do this.
I need:
1. to know how I would add an attachment to an email (and which API to use),
2. how I would use cron to send the emails to the desired group at a certain time,
3. how to retrieve users that have completed the course so that I could send emails (with attachment) to them.
Thanks in advance.
(I'm using moodle version 3.0)

This is an overview.
First create a local plugin. For example /local/yourplugin
https://docs.moodle.org/dev/Local_plugins
Then set up a message provider
https://docs.moodle.org/dev/Message_API
defined('MOODLE_INTERNAL') || die();
in local/yourplugin/db/messages.php
$messageproviders = array (
'coursecompleted' => array (
),
Then add an event observer - you will want to respond to the course_completed event
https://docs.moodle.org/dev/Event_2
in /local/yourpluginname/db/events.php
have something like
$observers = array(
array(
'eventname' => '\core\event\course_completed',
'callback' => 'local_yourplugin_observer::course_completed',
),
);
Now add the message code
Add something like this to '/local/message/classes/observer.php'
defined('MOODLE_INTERNAL') || die();
class local_yourplugin_observer {
/**
* Triggered when 'course_completed' event is triggered.
*
* #param \core\event\course_completed $event
* #return bool
*/
public static function course_completed(\core\event\course_completed $event) {
// Your code here.
$message = new \core\message\message();
$message->component = 'local_yourplugin'; // Name of your local plugin.
$message->name = 'coursecompleted'; // Name of message provider.
$message->userfrom = $USER;
$message->userto = $user;
$message->subject = 'message subject 1';
$message->fullmessage = 'message body';
$message->fullmessageformat = FORMAT_MARKDOWN;
$message->fullmessagehtml = '<p>message body</p>';
$message->smallmessage = 'small message';
$message->notification = '0';
$message->contexturl = 'http://GalaxyFarFarAway.com';
$message->contexturlname = 'Context name';
$message->replyto = "random#example.com";
$content = array('*' => array('header' => ' test ', 'footer' => ' test ')); // Extra content for specific processor
$message->set_additional_content('email', $content);
// Create a file instance.
$usercontext = context_user::instance($user->id);
$file = new stdClass;
$file->contextid = $usercontext->id;
$file->component = 'user';
$file->filearea = 'private';
$file->itemid = 0;
$file->filepath = '/';
$file->filename = '1.txt';
$file->source = 'test';
$fs = get_file_storage();
$file = $fs->create_file_from_string($file, 'file1 content');
$message->attachment = $file;
$messageid = message_send($message);
}
}

Related

Recaptcha for existing form ... the php part is giving me problems

Am not really a coder, but understand a little... Bought a web template with a contact form. It sends the form to a php for validation, which in turn sends it to me in an email. I can get the Recaptcha to appear fine on the form... But the php seems to fail (gives me a 500 error, but it DOES send out the form email to me)... Sorry... I'm tearing my hair out!
The following is the php file:
$response = $_POST["g-recaptcha-response"];
$url = 'https://www.google.com/recaptcha/api/siteverify';
$data = array(
'secret' => 'secret_code_here',
'response' => $_POST["g-recaptcha-response"]
);
$options = array(
'http' => array (
'method' => 'POST',
'content' => http_build_query($data)
)
);
$context = stream_context_create($options);
$verify = file_get_contents($url, false, $context);
$captcha_success=json_decode($verify);
if ($captcha_success->success==false) {
echo "<p>You are a bot! Go away!</p>";
} else if ($captcha_success->success==true) {
use VanillaForm\MailSender;
use VanillaForm\Utils;
require_once('inc/Utils.php');
require_once('inc/MailSender.php');
header('Access-Control-Allow-Origin: *');
/*
* Check if call is a POST request (data was sent by form).
* While it's not a POST request it returns OK, which can be handy with checking that the script is alive.
*/
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
if (function_exists('mail')) {
die('OK');
} else {
die('PHP parser works, but <b>mail()</b> function seems to doesn\'t exist');
}
}
/*
*
* Vanilla Configuration starts HERE
*
*/
$vf_config = array(
/*** Code Snippet - quick-start ***/
/**
* Recipient's e-mail. To this e-mail email will be sent.
* E.g. Single recipient
* 'emailRecipients' => 'john#domain.com',
*
* E.g. Multiple recipients
* 'emailRecipients' => 'john#domain.com, andy#domain.com',
*/
'emailRecipients' => 'my#email.com',
/**
* If is not empty it sets a header From in e-mail message (sets sender e-mail).
* Note: some hosting servers can block sending e-mails with custom From field in header.
* If so, leave this field as empty.
* E.g. Single recipient
* 'emailSender' => 'john#domain.com',
*/
'emailSender' => 'my#email.com'
/*** /Code Snippet - quick-start ***/
);
$vfSender = new MailSender($vf_config);
/*
* Some variable may need translation for better readability.
* You can access and modify variables by:
* $vfSender->data['variable-name']
*/
switch ($vfSender->data['gender']) {
case "F":
$vfSender->data['gender'] = "Female";
break;
case "M":
$vfSender->data['gender'] = "Male";
break;
default:
$vfSender->data['gender'] = "Not selected";
break;
}
// Define here subject of the e-mail message
$subject = 'Website Contact Form - New Message from '.$vfSender->data['name'];
// Define here content of the e-mail message
$content = "Hey,
You've received new message from your website. Check the details below:
Sender's IP address: ".Utils::getIp()."
Name: {NAME}
E-mail: {EMAIL}
Phone number: {TEL}
Subject: {SUBJECT}
Message:
{MESSAGE}
";
// Set subject and message content
$vfSender->setMessage($subject, $content);
/*
* Vanilla Configuration ends HERE
*/
die($vfSender->sendMessage());
}

Does not allow responding to a message sent with the moodle api

I trying to make a php script to send one message to other person in moodle.
I've seen the message api and i make this
$message = new \core\message\message();
$message->component = 'moodle';
$message->name = 'instantmessage';
$message->userfrom = 318;
$message->userto = 323;
$message->subject = 'message subject 1';
$message->fullmessage = 'message body';
$message->fullmessageformat = FORMAT_MARKDOWN;
$message->fullmessagehtml = '<p>message body</p>';
$message->smallmessage = 'small message';
$message->notification = '0';
$message->contexturl = 'http://GalaxyFarFarAway.com';
$message->contexturlname = 'Context name';
$message->replyto = "random#example.com";
$content = array('*' => array('header' => ' test ', 'footer' => ' test ')); // Extra content for specific processor
$message->set_additional_content('email', $content);
$message->courseid = 107; // This is required in recent versions, use it from 3.2 on https://tracker.moodle.org/browse/MDL-47162
$messageid = message_send($message)
The problem is, when the user 323 send a reply message in the chat that is created in the moodle internal messaging, an error occurs (the message is surrounded by red) and never arrives.
And I really want it to be able to respond as if it were a normal conversation.
I don't know if I'm going wrong.
Thank you
I finally found it !!!
The problem is that first you have to create a conversation between the users and then send the message
if(!\core_message\api::get_conversation_between_users([$userfrom, $userto ])){
$conversation = \core_message\api::create_conversation(
\core_message\api::MESSAGE_CONVERSATION_TYPE_INDIVIDUAL,
[
$userfrom,
$userto
]
);
}
$message = new \core\message\message();
$message->component = 'moodle';
$message->name = 'instantmessage';
$message->userfrom = $userfrom ;
$message->userto = $userto;
$message->subject = 'Nuevo mensaje';
$message->fullmessage = $msg;
$message->fullmessageformat = FORMAT_MARKDOWN;
$message->fullmessagehtml = $msg;
$message->smallmessage = $msg;
$message->notification = '0';
$message->contexturl = '';
$message->contexturlname = 'Context name';
$message->replyto = "##########.###";
$content = array('*' => array('header' => '', 'footer' => ''));
$message->set_additional_content('email', $content);
$message->courseid = 107;
message_send($message);
It might be because the userto and userfrom need to be objects eg:
$userto = $DB->get_record('user', array('id' => 323));
$message->userfrom = $USER; // Current user.
$message->userto = $userto;
see https://docs.moodle.org/dev/Message_API#How_to_send_a_message

Adding media to Twilio group messaging system

My group messaging app allowing people in a group (people.php) to sms each other in a closed system where all users can view and reply to the sms.
My next step would be to allow the media files which I can see on the Twilio Console to be sent to others in this group message system and possibly save a record of that media file.
This my code so far, it functions just missing the media part.
listener.php
<?php
include("../Services/Twilio.php");
include("config.php");
$client = new Services_Twilio($accountsid, $authtoken);
include("functions.php");
include("pdo.class.php");
include("people.php");
if( isset($_POST['Body']) ){
$phone = $_POST['From'];
$message = ($_POST['Body']);
$media = ($_POST['MediaUrl0']);
$name = $people[ $phone ];
if( empty($name) ) $name = $phone;
// resends sms message to group
$message = '['.$name.'] '.$message .$media;
foreach ($people as $number => $name) {
if( $number == $phone ) continue;
$sid = send_sms($number,$message,$media);
}
// reply message for succesfull sent sms
print_sms_reply("Message delivered");
// insert sms traffic into database for record purposes
$now = time();
$pdo = Db::singleton();
$sql = "INSERT INTO message_log SET `message`='{$message}', `sent_from`='{$name}'";
$pdo->exec( $sql );
}
?>
function.php
<?php
function send_sms($number,$message){
global $client,$fromNumber;
$sms = $client->account->sms_messages->create(
$fromNumber,
$number,
$message
);
return $sms->sid;
}
function print_sms_reply ($sms_reply){
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
echo "<Response>\n<Sms>\n";
echo $sms_reply;
echo "</Sms></Response>\n";
}
?>
people.php
<?php
include("config.php");
$conn=mysqli_connect("$dbhost","$dbuser","$dbpass","$dbname")
or die (mysqli_error());
$query = "SELECT phone, name FROM grouplist";
$result = mysqli_query($conn, $query);
$people = array();
while ($row = mysqli_fetch_assoc($result)) {
$people[$row['phone']] = $row['name'];
}
?>
Twilio developer evangelist here.
Looks like you need to update your send_sms function to include the media url. Something like this should work:
<?php
function send_sms($number,$message,$media_url){
global $client,$fromNumber;
$sms = $client->account->messages->create(array(
'To' => $number,
'From' => $fromNumber,
'Body' => $message,
'MediaUrl' => $media_url
);
return $sms->sid;
}
?>
Notably, I've updated the call from $client->account->sms_messages->create because the sms_messages resource is deprecated and cannot send media messages. Using $client->account->messages->create uses the newer Messages resource and means you will be able to send media messages.
Let me know if this helps at all.

Tabs not showing up in envelope created from template

I'm trying to create a embedded envelope based on a template. The problem I am having is that in the created envelope the tabs I have created are missing.
I searched around and found the role assignment and used that and still no luck. When I look at the XML the role is the same as the template as well as the routing order and ID.
I tried setting the template so that I can't delete any recipients and I get the error:
Uncaught SoapFault exception: [soap:Client] Required recipient in the template has not been provided. Recipient not satisfied for role, Signer, in template Test Form
Here is my PHP to create and send the envelope, a lot of this is code used from the documentation:
// Get the recipient from a post
$rcp1 = new Recipient(); // First recipient to put in recipient array
$rcp1->UserName = $_POST['Name'];
$rcp1->Email = $_POST['Email'];
$rcp1->Type = RecipientTypeCode::Signer;
$rcp1->ID = "1";
$rcp1->RoutingOrder = 1;
$rcp1->CaptiveInfo = new RecipientCaptiveInfo();
$rcp1->CaptiveInfo->ClientUserId = 1;
$rcp1->RoleName = "Signer";
$rcp1->RequireIDLookup = FALSE;
// Create Role Assignments
$assign = new TemplateReferenceRoleAssignment();
$assign->RecipientID = $rcp1->ID;
$assign->RoleName = $rcp1->RoleName;
// Use a server-side template
$templateRef = new TemplateReference();
$templateRef->TemplateLocation = TemplateLocationCode::Server;
$templateRef->RoleAssignments = $assign;
$templateRef->Template = "****";
// Construct the envelope info
$envInfo = new EnvelopeInformation();
$envInfo->AccountId = $AccountID;
$envInfo->Subject = "This is the Subject";
$envInfo->EmailBlurb = "I have no Idea What a blurb is";
// Send creates draft with all the template info
$createEnvelopeFromTemplatesparams = new CreateEnvelopeFromTemplates();
$createEnvelopeFromTemplatesparams->TemplateReferences = array($templateRef);
$createEnvelopeFromTemplatesparams->Recipients = array($rcp1);
$createEnvelopeFromTemplatesparams->EnvelopeInformation = $envInfo;
$createEnvelopeFromTemplatesparams->ActivateEnvelope = true;
$env = $api->CreateEnvelopeFromTemplates($createEnvelopeFromTemplatesparams);
$envStatus = $env->CreateEnvelopeFromTemplatesResult;
// Construct the recipient token authentication assertion and specify
// ID, start time, method, and domain
$assertion = new RequestRecipientTokenAuthenticationAssertion();
$assertion->AssertionID = guid();
$assertion->AuthenticationInstant = nowXsdDate();
$assertion->AuthenticationMethod = RequestRecipientTokenAuthenticationAssertionAuthenticationMethod::Password;
$assertion->SecurityDomain = "Request Recipient Token Test";
// Construct the URLs based on UserName
$recip = $envStatus->RecipientStatuses->RecipientStatus[0];
$urls = new RequestRecipientTokenClientURLs();
$urlbase = getCallbackURL('pop.php');
$urls->OnSigningComplete = $urlbase . "?event=SignComplete&uname=" . $recip->UserName;
$urls->OnViewingComplete = $urlbase . "?event=ViewComplete&uname=" . $recip->UserName;
$urls->OnCancel = $urlbase . "?event=Cancel&uname=" . $recip->UserName;
$urls->OnDecline = $urlbase . "?event=Decline&uname=" . $recip->UserName;
$urls->OnSessionTimeout = $urlbase . "?event=Timeout&uname=" . $recip->UserName;
$urls->OnTTLExpired = $urlbase . "?event=TTLExpired&uname=" . $recip->UserName;
$urls->OnIdCheckFailed = $urlbase . "?event=IDCheck&uname=" . $recip->UserName;
$urls->OnAccessCodeFailed = $urlbase . "?event=AccesssCode&uname=" . $recip->UserName;
$urls->OnException = $urlbase . "?event=Exception&uname=" . $recip->UserName;
// Send
$requestRecipientTokenparams = new RequestRecipientToken();
$requestRecipientTokenparams->EnvelopeID = $envStatus->EnvelopeID;
$requestRecipientTokenparams->ClientUserID = $recip->ClientUserId;
$requestRecipientTokenparams->Username = $recip->UserName;
$requestRecipientTokenparams->Email = $recip->Email;
$requestRecipientTokenparams->AuthenticationAssertion = $assertion;
$requestRecipientTokenparams->ClientURLs = $urls;
$response = $api->RequestRecipientToken($requestRecipientTokenparams);
$tokenUrl = $response->RequestRecipientTokenResult;
echo '<iframe src="' . $tokenUrl . '" width="100%" height="720px"></iframe>';
This is the recipient info that is returned when I RequestTemplate():
[0] => Recipient Object
(
[ID] => 1
[UserName] =>
[SignerName] =>
[Email] =>
[Type] => Signer
[AccessCode] =>
[AddAccessCodeToEmail] =>
[RequireIDLookup] =>
[IDCheckConfigurationName] =>
[PhoneAuthentication] =>
[SignatureInfo] =>
[CaptiveInfo] =>
[CustomFields] =>
[RoutingOrder] => 1
[IDCheckInformationInput] =>
[AutoNavigation] =>
[RecipientAttachment] =>
[Note] =>
[RoleName] => Signer
[TemplateLocked] =>
[TemplateRequired] => 1
[TemplateAccessCodeRequired] =>
[DefaultRecipient] =>
[SignInEachLocation] =>
)
This might be due to you instatiating the templateRoleAssignments as an object and not an array. Since you're using the SOAP api and not REST have you seen the DocuSign SOAP SDK up on Github? That has sample code and projects for 5 different environments including PHP (PHP, Java, C#, Ruby, and Salesforce):
https://github.com/docusign/DocuSign-eSignature-SDK
Looking at a function defined in the PHP project I see the following:
function createFinalRoleAssignments($recipients) {
$roleAssignments[] = new TemplateReferenceRoleAssignment();
foreach ($recipients as $r) {
$assign = new TemplateReferenceRoleAssignment();
$assign->RecipientID = $r->ID;
$assign->RoleName = $r->RoleName;
array_push($roleAssignments, $assign);
}
// eliminate 0th element
array_shift($roleAssignments);
return $roleAssignments;
}
Notice how $roleAssignments is declared as an array using square brackets [], I have a strong feeling that is causing your error. Try defining your roleAssignments the same way and that will probably work.

joomla 1.7 user registration customization issue

-> i am trying for new user registration customization.
-> for that i create form and hidden variable through call function from controller.
-> in controller save function i write this code but some inner function which not work in 1.7 so create problem here.
function register_save()
{
global $mainframe;
$db =& JFactory::getDBO();
// Check for request forgeries
JRequest::checkToken() or jexit( 'Invalid Token' );
//clean request
$post = JRequest::get( 'post' );
$post['username'] = JRequest::getVar('username', '', 'post', 'username');
$post['password'] = JRequest::getVar('password', '', 'post', 'string', JREQUEST_ALLOWRAW);
$post['password2'] = JRequest::getVar('password2', '', 'post', 'string', JREQUEST_ALLOWRAW);
// get the redirect
$return = JURI::base();
// do a password safety check
if(strlen($post['password']) || strlen($post['password2'])) { // so that "0" can be used as password e.g.
if($post['password'] != $post['password2']) {
$msg = JText::_('PASSWORD NOT MATCH');
// something is wrong. we are redirecting back to edit form.
// TODO: HTTP_REFERER should be replaced with a base64 encoded form field in a later release
$return = str_replace(array('"', '<', '>', "'"), '', #$_SERVER['HTTP_REFERER']);
if (empty($return) || !JURI::isInternal($return)) {
$return = JURI::base();
}
$this->setRedirect($return, $msg, 'error');
return false;
}
}
// Get required system objects
$user = clone(JFactory::getUser());
$pathway = JFactory::getApplication();
//$pathway =& $mainframe->getPathway();
$config =& JFactory::getConfig();
//print_r($config)."<br>";
$authorize =& JFactory::getACL();
//print_r($authorize)."<br>"; /// some mistake here
$newUsertype = 'Registered';
// Bind the post array to the user object
if (!$user->bind( JRequest::get('post'), 'usertype' )) {
JError::raiseError( 500, $user->getError());
}
// Set some initial user values
$user->set('id', 0);
$user->set('usertype', $newUsertype);
$user->set('gid', $authorize->get_group_id( '', $newUsertype, 'ARO' ));
$date =& JFactory::getDate();
$user->set('registerDate', $date->toMySQL());
// If user activation is turned on, we need to set the activation information
jimport('joomla.user.helper');
$user->set('activation', JUtility::getHash( JUserHelper::genRandomPassword()) );
$user->set('block', '1');
// If there was an error with registration, set the message and display form
if ( !$user->save() )
{
JError::raiseWarning('', JText::_( $user->getError()));
$this->register();
return false;
}
$obj1 = new stdClass();
$obj1->userid = $user->id;
$obj1->points = 0;
$obj1->posted_on = $date->toMySQL();
$obj1->avatar = '';
$obj1->thumb = '';
$obj1->params = 'notifyEmailSystem=1
privacyProfileView=0
privacyPhotoView=0
privacyFriendsView=0
privacyVideoView=1
notifyEmailMessage=1
notifyEmailApps=1
notifyWallComment=0';
$db->insertObject('#__community_users', $obj1, 'userid');
$extra_field = array(1=>2,2=>3,3=>4,4=>6,5=>7,6=>8,7=>9,8=>10,9=>11,10=>12,11=>14,12=>15,13=>16);
$i = 1;
$obj2 = new stdClass();
while($extra_field[$i] != "")
{
$obj2->id = '';
$obj2->user_id = $user->id;
$obj2->field_id = $extra_field[$i];
$obj2->value = '';
$db->insertObject('#__community_fields_values', $obj2, 'id');
$i++;
}
////////// end of joomsocial customisation///////////////////////////
// Send registration confirmation mail
$password = JRequest::getString('password', '', 'post', JREQUEST_ALLOWRAW);
$password = preg_replace('/[\x00-\x1F\x7F]/', '', $password); //Disallow control chars in the email
UserControllerRegister::_sendMail($user, $password);
// Everything went fine, set relevant message depending upon user activation state and display message
$message = JText::_( 'Your account has been created and an activation link has been sent to the e-mail address you entered. Note that you must activate the account by clicking on the activation link when you get the e-mail before you can login.' );
$this->setRedirect('index.php', $message);
}
not insert record in table.
please help me.
I think you're right:
Joomla 1.5 ACL (Access Control Lists) is hierarchical: each user group inherits permissions from the groups below it.
In Joomla 1.7 ACL is not necessarily hierarchical. You can setup groups with whatever permissions you wish.
The difference between the ACL in Joomla 1.5 and 1.7 is not only in the behavior - but also in the implementation! which means that the authentication/registration mechanism will be implemented in different ways:
http://www.youtube.com/watch?v=ZArgffnPUo4

Categories