How to send email using rails 4 - ruby-on-rails-4.1

I am trying to send an email and I follow this tutorial
http://guides.rubyonrails.org/action_mailer_basics.html
and this is how I proceed:
my emailer.rb
class Emailer < ActionMailer::Base
default from: "r.karoui#gmail.com"
def emprunt_mail(user)
#user = user
#url = 'http://example.com/login'
mail(to: #user.email, subject: 'Emprunt de livre')
end
end
my emrunt_mail.erb.html
<!DOCTYPE html>
<html>
<head>
<meta content='text/html; charset=UTF-8' http-equiv='Content-Type' />
</head>
<body>
<h1>Bonjour, <%= current_user.f_name %></h1>
<p>
Vous venez d'emprunter un livre
</p>
<p>
vous avez une durée d'une semaine pour le rendre !
</p>
<p>Bonne journée!</p>
</body>
</html>
in my books_controller.rb
def emprunter
if (#book.state == false)
if #book.update(state: 1)
flash[:notice]='Vous aver un délai de 7 jours pour rendre le livre'
Emailer.create_emprunt_mail(current_user)
Emailer.deliver_emprunt_mail(current_user)
redirect_to books_list_path
else
redirect_to admin_manage_path
end
else
flash[:notice]='Ce livre est déja pris'
redirect_to books_list_path
end
end
I add this confguration to mt environment/developpment.rb
config.assets.raise_runtime_errors = true
config.action_mailer.raise_delivery_errors =true
config.action_mailer.default_url_options ={ :host => 'localhost:3000'}
config.action_mailer.smtp_settings= {
adress: "smtp.gmail.com",
port: "587",
domain: "gmail.com",
authentication: "plain",
enable_startlls_auto: true,
user_name: 'USERNAME',
password: '*********'
}
and I did not add any route
the strage bihavior is that in emprunter method it pass to the else of the first if and it should enter to the block if .
update
in my server i have now this
" Rendered emailer/emprunt_mail.html.erb (0.0ms)
Emailer#emprunt_mail: processed outbound mail in 4.1ms
Sent mail to rawia.seller#gmail.com (3.3ms)
Date: Tue, 11 Nov 2014 11:40:31 +0100
From: karoui.rawia#gmail.com
To: rawia.seller#gmail.com
Message-ID: <5461e79fd9674_4b33ffe529d82a44d0#imac-de-imac.home.mail>
Subject: Emprunt de livre
Mime-Version: 1.0
Content-Type: text/html;
charset=UTF-8
Content-Transfer-Encoding: quoted-printable
<!DOCTYPE html>
<html>
<head>
<meta content=3D'text/html; charset=3DUTF-8' http-equiv=3D'Content-Type=
' />
</head>
<body>
<h1>Bonjour, </h1>
<p>
Vous venez d'emprunter un livre
</p>
<p>
vous avez une dur=C3=A9e d'une semaine pour le rendre !
</p>
<p>Bonne journ=C3=A9e!</p>
</body>
</html>=
Redirected to http://localhost:3000/books/show
Completed 302 Found in 14ms (ActiveRecord: 1.2ms)
but when i check for mail i did not find any new one!! Could please tell me where is the problem
this is the new configuration in environment/developpment.rb:
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
# ActionMailer Config
# Setup for production - deliveries, no errors raised
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = false
config.action_mailer.default :charset => "utf-8"
config.action_mailer.smtp_settings= {
adress: "smtp.gmail.com",
port: 587,
domain: "gmail.com",
authentication: "plain",
enable_starttls_auto: true,
user_name: 'username',
password: '*****'
}

Related

Data communication between two userInterface (ui) - Apps script refer to client instantiated sidebar

For the use of a google sheet stock management by several people, I use a sidebar for authentication (login). This running well, but i would like to allow different and simultaneous authentications (on different client computers)
In fact, my google scripts andZ html forms (integrated in userInterfaces) should be able to know and use the current agent, memorized by a sidebar field, as long as it is not closed.
I tried to use userProperties, scriptProperties, documentProperties,and cacheService but the connected agent is then memorized and common for all users instead of being specific to each workstation running the application. I have to work on the client side.
I know how to read and modify the DOM of the sidebar by the javascript code that i place there and also to recover this information within my google script. But here it is in fact a question of finding information from the instantiated sidebar.
My Apps Script:
function init_SideBar(e) { // init & show the sidebar
htmlSideBar = HtmlService.createHtmlOutputFromFile('htmlSideBar')
.setTitle('htmlSideBar')
.setWidth(300);
htmlSideBar.info="blabla"; // could it be a lead ?
SpreadsheetApp.getUi().showSidebar(htmlSideBar);
}
function gScriptFcGiveToSidebar() { // to send datas in an array to html page
let jSONforSheet= JSON.stringify(objForSheet);
return jSONforSheet;
}
function calledFromFormSubmit(sidebarForm) { // Receive datas from html sidebar
agentConnected=sidebarForm;
if(agentConnected=="Deconnecté"){
ss.toast("Deconnecté")
}else{
ss.toast("Bonjour "+agentConnected);
}
}
htmlSideBar.html:
<html>
<head>
<title>HTML DOM Objects</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
</head>
<body>
<label for="dowloading">dowloading</label>
<script>
function submitForm() { // envoi les données du form "sidebarForm" vers la fonction qui dans google script va les récupérer
// login & password verification (tablUser contains a column au login and a column of mp)
var elmts=document.getElementById("sidebarForm");
for(let iUsers=0;iUsers<sidebarObj.tablUser.length;iUsers++){
if (sidebarObj.tablUser[iUsers][0]==elmts.agentId.value){
if(sidebarObj.tablUser[iUsers][1]==elmts.mpId.value ){
document.getElementById('labelConnectId').innerHTML =elmts.agentId.value;
google.script.run.calledFromFormSubmit(elmts.agentId.value);
return;
}
}
}
alert ("password false, try again");
}
function deconnect(){
document.getElementById('labelConnectId').innerHTML ="Deconnecté";
document.getElementById('agentId').value ="Deconnecté";
google.script.run.calledFromFormSubmit("Deconnecté");
}
function jsFcGiveToForm(jSONforSheet){ //
$('#rangeResult').text(jSONforSheet); //$('#rangeResult').text(<nom de la variable qui va finalement délivrer au js, les données du google script>)
sidebarObj=JSON.parse(jSONforSheet);
document.write('<label id="labelConnectId" form="sidebarForm" > '+sidebarObj.agentConnected+'</label>');
document.write('<br><input type="button" value="Deconnect" onclick="deconnect();" />');
document.write('<form id="sidebarForm">');
document.write('<select name="agent" id="agentId">');
document.write('<option value="'+sidebarObj.agentConnected+'">'+sidebarObj.agentConnected+'</option>');
for(let iUsers=0;iUsers<sidebarObj.tablUser.length;iUsers++){
document.write('<option value="'+sidebarObj.tablUser[iUsers][0]+'">'+sidebarObj.tablUser[iUsers][0]+'</option>');
}
document.write('</select>');
document.write('<br /><input type="text" name="mp" id="mpId" value="password">');
document.write('<br /><input type="button" value="Submit" onclick="submitForm();" />');
document.write('<input type="button" value="Close" onclick="google.script.host.close()" />');
}
document.close(); // HYPER IMPORTANT !! libere le navigateur pour qu il continu a charger la page
google.script.run.withSuccessHandler(jsFcGiveToForm).gScriptFcGiveToSidebar();
</script>
</form>
</body>
</html>
Some leads ? :
Must i use scriptless
<?= blablabla?>
Using Meta tags :
var x = document.createElement("META");
x.setAttribute("name", "description");
x.setAttribute("content", "blablabla");
document.head.appendChild(x);
Using a property of htmlOutpu:
htmlSideBar.info="blabla";
Thanks a lot for your participation ! :)
I found a solution and described the sequences using the commented steps A1-4 and B1-12) which you just have to follow
Sidebar.gs:
function init_SideBar(e) { //A-1) init & show the sidebar.html
htmlSideBar = HtmlService.createHtmlOutputFromFile('htmlSideBar')
.setTitle('htmlSideBar')
.setWidth(300);// n'est plus modifiable fixé par google à 300 px
htmlSideBar.info="blabla";
HtmlService.SandboxMode=HtmlService.XFrameOptionsMode;
SpreadsheetApp.getUi().showSidebar(htmlSideBar);
}
function gScriptFcGiveToSidebar() { // A-3) to send google sheet datas (array or json...) to htmlSideBar.html page
let jSONforSheet= JSON.stringify(objForSheet);
ss.toast("json"+jSONforSheet);
return jSONforSheet;
}
function gScriptFromSidebarThenGiveToFormIn(sidebarAgent,provenanceFlag){
//Browser.msgBox("2 4 sidebarAgent="+sidebarAgent+" cache="+cacheService.get('sidebarAgent')+"init="+init);
if (provenanceFlag==false) { // B-7) Called by the de html htmlFormIn...withSuccessHandler(jsFcGiveToFormIn)
// Utilities.sleep(8000); // simulating an excess of a retention time of the cache
sidebarAgent=cacheService.get('sidebarAgent'); // B-8) Retieve the useful data in the cache
if (sidebarAgent==null) {return "echec";} // B-9) Abort in case the cache got lost (retention time exceeded)
cacheService.remove('sidebarAgent'); // B-10) Free the cache
return sidebarAgent; //B-11) give to formIn.html the data it expects
}else{ // B-2) provenanceFlag=true means that the call is from the htmlSideBar.html file buton.onclick , (sidebarAgent has the useful data)
if (cacheService.get('sidebarAgent')!=null) return false // B-3) cache not freed, abort proces for try again in a few time
cacheService.put('sidebarAgent',sidebarAgent,5); // B-4) Stock in cache the data for 5 secondes
initFormIn(sidebarAgent); //B5 open the user interface formIn.html that will have to take imediately the data in the cache, then free it
}
}
function calledFromFormSubmit(sidebarForm) { // Receive datas from html sidebar
agentConnected=sidebarForm;
//userProperties.setProperty('agentConnected', agentConnected);
if(agentConnected=="Deconnecté"){
ss.toast("Deconnecté")
}else{
ss.toast("Bonjour "+agentConnected);
}
//SpreadsheetApp.getActiveSheet().appendRow(["test",sidebarForm]);
}
htmlSideBar.html:
<!DOCTYPE html>
<html>
<head>
<style>
body { font-size:1em; }
p { color : red; }
</style>
<title>HTML DOM Objects</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
</head>
<body>
<label for="dowloading">dowloading</label>
<?= info?>
<script>
function callFormIn(){ google.script.run.gScriptFromSidebarThenGiveToFormIn(document.getElementById("labelConnectId").innerHTML,true);
}
function submitForm() { // My connect process
var elmts=document.getElementById("sidebarForm");
for(let iUsers=0;iUsers<sidebarObj.tablUser.length;iUsers++){
if (sidebarObj.tablUser[iUsers][0]==elmts.agentId.value){
if(sidebarObj.tablUser[iUsers][1]==elmts.mpId.value ){
document.getElementById('labelConnectId').innerHTML =elmts.agentId.value;
google.script.run.calledFromFormSubmit(elmts.agentId.value);
return;
}
}
}
alert ("mp faux");
}
function writeLabelAndTxtBox(name,id,value){
document.write('<br /><label for="'+name+'">'+name+': </label>');
document.write('<br /><input type="text" name="'+name+'" id="'+id+'" value="'+value+'">');
}
function writeLabel(name){
document.write('<br /><label for="'+name+'">'+name+': </label>');
}
function writeTxtBox(name,id,value){
document.write('<br /><input type="text" name="'+name+'" id="'+id+'" value="'+value+'">');
}
// -----------------------------------------------------------------------------------------------------------------
function clearAndClose(){
google.script.host.close();
}
function deconnect(){
document.getElementById('labelConnectId').innerHTML ="Deconnecté";
document.getElementById('agentId').value ="Deconnecté"; // facultatif ?
google.script.run.calledFromFormSubmit("Deconnecté");
}
function jsFcGiveToSidebar(jSONforSheet){ // A-4) I can Fill the sidebar.html page with json datas received from apps script about goole sheet
// End of the A1-4) states
sidebarObj=JSON.parse(jSONforSheet); // in particular sidebarObj.tablUser[] that contains the sheet columns of logins and passwords
/* sidebarObj.agentConnected was used to don't have to connect when open a new sidebar
(I dont speak aubout the google acount connection)
sidebarObj.keepConnectPropertie==false desactive this mode
i prefer now have to connect on each new sidebar instentiation.
the login is preserved while the sidebar is instantiated.
*/
document.write(new Date().toLocaleDateString());
if (sidebarObj.keepConnectPropertie==false){sidebarObj.agentConnected="Deconnecté"}
document.write('<label id="labelConnectId" form="sidebarForm" > '+sidebarObj.agentConnected+'</label>');
document.write('<br><input type="button" value="Deconnect" onclick="deconnect();" />');
document.write('<form id="sidebarForm">');
document.write('<select name="agent" id="agentId">');
document.write('<option value="'+sidebarObj.agentConnected+'">'+sidebarObj.agentConnected+'</option>');
for(let iUsers=0;iUsers<sidebarObj.tablUser.length;iUsers++){
document.write('<option value="'+sidebarObj.tablUser[iUsers][0]+'">'+sidebarObj.tablUser[iUsers][0]+'</option>');
}
document.write('</select>');
writeTxtBox('mp','mpId','password')
document.write('<br><input type="button" value="Submit" onclick="submitForm();" />');
document.write('<br><input type="button" value="FormIn" onclick="callFormIn();" />'); // B-1) run gScriptFromSidebarThenGiveToFormIn() with data parameter needed
document.write('<input type="button" value="Close" onclick="google.script.host.close()" />');
}
document.close();
google.script.run.withSuccessHandler(jsFcGiveToSidebar).gScriptFcGiveToSidebar(); // A-2) give to jsFcGiveToSidebar() the return of gScriptFcGiveToSidebar()
</script>
</form>
</body>
</html>
htmlFormIn.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<style type="text/css">
.myDiv {cursor:pointer;}
.divBlack{background-color:#000; color:#fff;}
</style>
<label for="dowloading">dowloading</label>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script>
// ---------------------------------------------- Functions for Javascript ------------------
function writeLabel(name){
document.write('<br /><label for="'+name+'">'+name+': </label>');
}
function writeTxtBox(name,id,value,prefix){
prefix=prefix||'<br />';
document.write(prefix+'<input type="text" name="'+name+'" id="'+id+'" value="'+value+'">');
}
// -------------------------------------------------Wrinting in Body -----
function addRow(){
cptLine++;
//alert(sidebarAgent); // alert(document.getElementById("idLblSidebarAgent").innerHTML);
//document.getElementById("tableForm").appendChild("tr");
let newLin = document.getElementById("tableForm").insertRow(-1); // ajoute un <tr> à la fin de la table
let newCell=newLin.insertCell(0); // ajoute un <td>
newCell.innerHTML = '<input type="text" name="" id=c"'+cptLine+'" value="v'+cptLine+'"> <input type="text" name="" id=d"'+cptLine+'" value="'+sidebarAgent+'">';
//alert("ajouté");
}
function jsFcGiveToFormIn(aagent){ // B-12) aagent receive the data value return from gScriptFromSidebarThenGiveToFormIn that have been called in A6 state
// B-13) the formIn.html can fill its fields :) - End of the B1-12) states
if (aagent=="echec"){ alert ("htmlFormIn 71 le cache service n'a pas memorisé assez longemps le transfert de donnée depuis la sidebar")}
sidebarAgent=aagent; // pour étendre la portée de cette info dans le script de cette page html
document.write('<label id="idLblSidebarAgent" for="info">'+sidebarAgent+'</label>')
writeTxtBox("Saisie","idSaisie","Entrez un code");
document.getElementById("idSaisie").addEventListener("click", addRow);
document.write('<form id="sidebarForm">');
document.write('<table id="tableForm"><tr id="r'+cptLine+'""><td>');writeTxtBox("Date","iddat","date"," ");writeTxtBox("Ref","idRef"+cptLine,""," ");
writeTxtBox("agent","idAgent",sidebarAgent," ");
document.write('</td></tr>')
document.write('</table>')
document.write('</form>');
}
document.close();
var cptLine=0;
var sidebarAgent;
google.script.run.withSuccessHandler(jsFcGiveToFormIn).gScriptFromSidebarThenGiveToFormIn("",false); // B-6) give to jsFcGiveToFormIn the return of gScriptFromSidebarThenGiveToFormIn("",provenanceFlag=false) with provenanceFlag=false that meaning the call is from formIn.html file.
</script>
</body>
</html>

how to put an array of arguments in path url in twig

i'm trying to pass an array of string in pth url, how can i put the for in teh path
i try to make a button on a twig in a app symfony
<a href="{{ path('cheops_glpi_tracking_search', {'status[]':{% for statu in status %} statu {% endfor %},'cheops_Glpi':1,'fkEntities_cheops_Glpi':tracking.fkEntities.id}) }}" target="_blank" class="btn" style="border:none;border-radius:75%;
border-bottom:3px solid #f03c0c;font:bold 13px Arial;color:#56504e;background:#fff;">
Voir tickets
</a>
Message : A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "operator" of value "%".
Une erreur s'est produite sur l'intranet ou vous n'avez pas accès à cette partie. Nous avons été automatiquement prévenu de cette erreur et allons régler le problème dans les plus brefs délais.
I'm not sure you can inline a for loop that way.
Instead you could join the elements the following way
Voir tickets

Passing twig data to vue js in symfony 4

I am using a component named "vue-cookie-law in my symfony application so I call it like that in my base (default twig template):
<div id="CookieLaw" data-locale="{{ app.request.locale }}"></div>
and then in my vue template I have this:
<template>
<div id="CookieLaw">
<cookie-law theme="base" transitionName="slideFromBottom">
<div slot="message">{{ locale }}En poursuivant votre navigation sur notre site vous acceptez l'utilisation de cookies, pour vous proposer des contenus personnalisés en fonction de vos centres d'intérêt et mesurer la fréquentation de nos services, pour en savoir plus et paramétrer les cookies, cliquez ici </div>
</cookie-law>
</div>
</template>
<script>
import CookieLaw from 'vue-cookie-law'
export default {
data() {
return {
locale: ""
}
},
components: { CookieLaw },
beforeMount: () => {
this.locale = this.$el.attributes['data-locale'].value;
}
}
</script>
<style scoped>
.Cookie {
background: white;
padding: 2rem;
}
</style>
And my js part :
import Vue from 'vue';
import CookieLaw from './components/CookieLaw';
new Vue({
el: '#CookieLaw',
render: h => h(CookieLaw)
});
So I try to pass the locale variable of my app but I have an error like that :
[Vue warn]: Error in beforeMount hook: "TypeError: _this.$el is undefined
So it seems I can't access my data attributes like that. Any idea on what I'm doing the wrong way here ? could it be a conflict between twig and vue ?
Have you checked the value of this.$el? I suspect that it targets <div id="CookieLaw" data-locale="{{ app.request.locale }}"></div> but in that case the latter element would be replaced by your Vue template.
If that's the case you should put the data-attribute in an element over it and instead of this.$el.attributes['data-locale'].value you write this.$el.previousElementSibling.getAttribute('data-locale').value
I would like to add also that your lifecycle hook is beforeMount but your element does not still exist at this point; try with mounted()instead

Can't send a variable to twig in order to send an email

I want to send an confirmation email, but I can't send the variable of my form to my email
Here's my code
if($form->isValid() && $form->isSubmitted()) {
$NewsLetters = $form->getData();
if(!$NewsLetters->getNom()) {
$NewsLetters->setNom("Anonyme");
}
$em->persist($NewsLetters);
$em->flush();
$nom = $NewsLetters->getNom();
$message = (new \Swift_Message('Confirmation d\'inscription à la newsletter'))
->setFrom('ez#zezezezeeze.fr')
->setTo($NewsLetters->getEmail())
->setBody(
$this->renderView('emails/confirmationEmail.html.twig'),
array('nom' => $nom, //HERE
),
'text/html'
);
$this->get('mailer')->send($message);
But twig give me this error
Variable "nom" does not exist in emails\confirmationEmail.html.twig at line 4.
<html>
<body>
Vous avez été inscrit avec succès à la Newsletter : {{ nom }}
{#{{ newsletterWebsite }} {{ newsletterStylo }} {{ newsletterCrayon }}#}
</body>
</html>
Normally it's work
Thanks for your help !
Seems a problem of wrong indentation: the array with params should be passed as second argument of the renderView method as follow:
$message = (new \Swift_Message('Confirmation d\'inscription à la newsletter'))
->setFrom('ez#zezezezeeze.fr')
->setTo($NewsLetters->getEmail())
->setBody(
$this->renderView(
'emails/confirmationEmail.html.twig',
array('nom' => $nom),
), // close renderView
'text/html'
); // close setBody
Hope this help

Generate excel sheet from classic asp on click of button

I want to create an excel sheet from click of button.
These excel sheet will contain report which is generated on classic asp page. When user clicks on button then an excel sheet should be created which will have the same report as page have
This header works fine:
<%
Response.AddHeader "Content-Disposition", "attachment;filename=NOMBRE_ARCHIVO.xls"
Response.ContentType = "application/vnd.ms-excel"
%>
For small tables, try this example in html/javascript:
<html>
<body>
<table id="tabla" border="1">
<tr><th>Uno</th><td>1</td></tr>
<tr><th>Dos</th><td>2</td></tr>
</table>
<p>
<input type="button" onclick="javascript:exportarExcel('tabla');" value="Vamos al excel!">
</p>
</body>
<script type="text/javascript">
function exportarExcel(tabla){
var t = document.getElementById(tabla);
t.border = 1;
var html = t.outerHTML;
html = encodeURIComponent(html);
// problemas con el encoding!
// se puede usar base64_encode() en lugar de encodeURIComponent(html))
// ojo con encodeURIComponet() que está deprecada. lo mejor sería usar base64
window.open('data:application/vnd.ms-excel,' + html);
}
</script>
</html>

Resources