ktor send email with html template - email

I am wondering what is the correct way of sending HTML templates with ktor via email.
This answer Sending Emails From Ktor Application can help inline HTML, or simple string but not hbs or other templates which can be used in ktor.
email service will work, but I do want to use a template. And doing it via MustacheContent will not work
package com.meet.utils.email
import com.meet.utils.Constants
import org.apache.commons.mail.DefaultAuthenticator
import org.apache.commons.mail.HtmlEmail
fun sendForgotPasswordEmail(token: String, emailTo: String) {
val email = HtmlEmail()
email.hostName = "smtp.sendgrid.net"
email.setSmtpPort(587)
email.setAuthenticator(
DefaultAuthenticator(
"apikey",
"API_KEY"
)
)
email.isSSLOnConnect = true
email.setFrom(Constants.EMAIL_FROM)
email.subject = "Forgot Password"
email.setHtmlMsg("<html><body><div style='background:red;'>Hello</div></body></html>")
email.addTo(emailTo)
email.send()
}
What I want to do is
email.sendTemplate(MustacheContent("forgotPassword.hbs", mapOf("token" to token)))
how I can send this?
resources/templates/reset.hbs
<html>
<body>
<h1>Hello</h1>
<p>Please visit the link below to reset your password</p>
Reset your password
</body>
</html>

You can compile and render a template via a Mustache factory to get an HTML string. Here is an example:
val factory = DefaultMustacheFactory("templates")
embeddedServer(Netty, port = 3333) {
install(Mustache) {
mustacheFactory = factory
}
routing {
post("/") {
val content = MustacheContent("forgotPassword.hbs", mapOf("token" to "my-token"))
val writer = StringWriter()
factory.compile(content.template).execute(writer, content.model)
val html = writer.toString()
// Send email with an HTML
}
}
}.start(wait = true)

Related

Sending email via SendGrid after form submission

I'm putting together a contact form using Svelte and SendGrid. Here is a basic app.svelte:
<script>
import sgMail from '#sendgrid/mail';
sgMail.setApiKey(import.meta.env.VITE_SENDGRID);
function submitForm() {
const msg = {
to: 'test#example.com',
from: 'test#example.com',
subject: 'Sending with SendGrid is Fun',
text: 'and easy to do anywhere, even with Node.js',
html: '<strong>and easy to do anywhere, even with Node.js</strong>'
};
console.log('Form submitted');
sgMail.send(msg);
}
</script>
<form on:submit|preventDefault={submitForm}>
<button type="submit">Submit</button>
</form>
The code above does not send an email after the user selects submit on the form, despite the function being called (it logs Form submitted in the console). When I move all code from submitForm() outside the function, the code executes on page load, so I know it's not an issue with my API key.
Any suggestions what I am missing?
Svelte is a frontend environment only. The Sendgrid package is desinged for a server side / node.js environment. In your example, your Sendgrid API key would be exposed because you're trying to use it on the frontend / client side.
A solution may be to look at SvelteKit, which has the concept of 'endpoints' which always run on the server side. Or you can create an express server to handle the sending of email to Sendgrid.
EDIT: The solution is to use Sveltekit endpoints. Endpoints always run on the server. Your final solution may look something like this:
File: /src/routes/api/sendmail.ts or /src/api/sendmail.js
import sgMail from "#sendgrid/mail";
sgMail.setApiKey(import.meta.env.VITE_SENDGRID);
export async function get(page) {
const msg = {
to: "test#example.com",
from: "test#example.com",
subject: "Sending with SendGrid is Fun",
text: "and easy to do anywhere, even with Node.js",
html: "<strong>and easy to do anywhere, even with Node.js</strong>",
};
console.log("Form submitted");
const output = await sgMail.send(msg);
return {
body: output,
};
}
File /src/routes/index.svelte
<script>
function submitForm() {
fetch("/api/sendmail");
}
</script>
<form on:submit|preventDefault={submitForm}>
<button type="submit">Submit</button>
</form>

Django 2 UserCreationForm not creating user

I'm using django-email-as-username so users can authenticate without a username and use their email instead. It seems that when I try to register a new user, I'm redirected back to the form page and the user isn't created. Am I supposed to be including the cleaned_data in my view?
Any advice?
forms.py
from django import forms
from django.contrib.auth import (authenticate, get_user_model,
password_validation)
from django.contrib.auth.forms import ReadOnlyPasswordHashField
from django.utils.translation import ugettext_lazy as _
from cuser.models import CUser
UserModel = get_user_model()
class AuthenticationForm(forms.Form):
"""
Base class for authenticating users. Extend this to get a form that accepts
email/password logins.
"""
email = forms.EmailField(
label=_("Email address"),
max_length=254,
widget=forms.EmailInput(attrs={'autofocus': True}),
)
password = forms.CharField(
label=_("Password"),
strip=False,
widget=forms.PasswordInput,
)
error_messages = {
'invalid_login': _(
"Please enter a correct %(username)s and password. Note that both "
"fields may be case-sensitive."
),
'inactive': _("This account is inactive."),
}
def __init__(self, request=None, *args, **kwargs):
"""
The 'request' parameter is set for custom auth use by subclasses.
The form data comes in via the standard 'data' kwarg.
"""
self.request = request
self.user_cache = None
super().__init__(*args, **kwargs)
self.username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD)
def clean(self):
email = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
if email and password:
self.user_cache = authenticate(self.request, email=email, password=password)
if self.user_cache is None:
# An authentication backend may reject inactive users. Check
# if the user exists and is inactive, and raise the 'inactive'
# error if so.
try:
self.user_cache = UserModel._default_manager.get_by_natural_key(email)
except UserModel.DoesNotExist:
pass
else:
self.confirm_login_allowed(self.user_cache)
raise forms.ValidationError(
self.error_messages['invalid_login'],
code='invalid_login',
params={'username': self.username_field.verbose_name},
)
else:
self.confirm_login_allowed(self.user_cache)
return self.cleaned_data
def confirm_login_allowed(self, user):
"""
Controls whether the given User may log in. This is a policy setting,
independent of end-user authentication. This default behavior is to
allow login by active users, and reject login by inactive users.
If the given user cannot log in, this method should raise a
``forms.ValidationError``.
If the given user may log in, this method should return None.
"""
if not user.is_active:
raise forms.ValidationError(
self.error_messages['inactive'],
code='inactive',
)
def get_user_id(self):
if self.user_cache:
return self.user_cache.id
return None
def get_user(self):
return self.user_cache
class UserCreationForm(forms.ModelForm):
"""
A form that creates a user, with no privileges, from the given email and
password.
"""
error_messages = {
'password_mismatch': _("The two password fields didn't match."),
}
email = forms.EmailField(
label=_("Email address"),
max_length=254,
widget=forms.EmailInput(attrs={'autofocus': True}),
)
password1 = forms.CharField(
label=_("Password"),
strip=False,
widget=forms.PasswordInput,
help_text=password_validation.password_validators_help_text_html(),
)
password2 = forms.CharField(
label=_("Password confirmation"),
widget=forms.PasswordInput,
strip=False,
help_text=_("Enter the same password as before, for verification."),
)
class Meta:
model = CUser
fields = []
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError(
self.error_messages['password_mismatch'],
code='password_mismatch',
)
return password2
def _post_clean(self):
super()._post_clean()
# Validate the password after self.instance is updated with form data
# by super().
password = self.cleaned_data.get('password2')
if password:
try:
password_validation.validate_password(password, self.instance)
except forms.ValidationError as error:
self.add_error('password2', error)
def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user
class UserChangeForm(forms.ModelForm):
email = forms.EmailField(
label=_("Email address"),
max_length=254,
widget=forms.EmailInput(),
)
password = ReadOnlyPasswordHashField(
label=_("Password"),
help_text=_(
"Raw passwords are not stored, so there is no way to see this "
"user's password, but you can change the password using "
"this form."
),
)
class Meta:
model = CUser
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['password'].help_text = self.fields['password'].help_text.format('../password/')
f = self.fields.get('user_permissions')
if f is not None:
f.queryset = f.queryset.select_related('content_type')
def clean_password(self):
# Regardless of what the user provides, return the initial value.
# This is done here, rather than on the field, because the
# field does not have access to the initial value
return self.initial["password"]
views.py
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render, redirect
from django.urls import reverse
from .forms import UserCreationForm
def index(request):
return HttpResponse("This will be the profile homepage.")
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/accounts')
else:
form = UserCreationForm()
return render(request, 'accounts/register.html', {'form': form})
urls.py
from django.urls import path
from django.conf.urls import include, url
from accounts import views
urlpatterns = [
path('', views.index, name='index'),
path('register/', views.register, name='register'),
register.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div>
<h1>Register</h1>
<form method="post" action="">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
</div>
</body>
</html>
Have you looked at custom user documentation? Seems to mention exactly what you mentioned, but as a caveat it requires you to do it on the first migration

Change the design of email body

I have written the code for sending email in email.js as follows:
Accounts.emailTemplates.siteName = "xyz";
Accounts.emailTemplates.from = "xyz <admin#xyz.com>";
Accounts.emailTemplates.verifyEmail = {
subject() {
return "[xyz] Verify Your Email Address";
}
};
Accounts.emailTemplates.verifyEmail.text = function( user, url) {
let emailAddress = user.emails[0].address,
urlWithoutHash = url.replace( '', '' ),
supportEmail = "support#xyz.com",
emailBody = `To verify your email address (${emailAddress}) visit the following link:\n\n${urlWithoutHash}\n\n If you did not request this verification, please ignore this email. If you feel something is wrong, please contact our support team: ${supportEmail}.`;
return emailBody;
}
The email is working and all I want is to change the Design. How to design the email body? Can I insert the html code inside the email body so that I can have a proper responsive email design? I have tried in many ways. Can anyone please help me out?
I have used mail gun API for sending emails is there anyway to use template.
I have tried with grunt email template and am struck with that I need help to get complete my task.
You can create an email template using SSR package.
Accounts.emailTemplates.verifyEmail.html = function (user, url) {
SSR.compileTemplate( 'registartionEmail', Assets.getText( 'email_templates/registration_confirm.html' ) );
var emailData = {
x: y;
};
return SSR.render( 'registartionEmail', emailData );
};
To handle the process of converting templates into raw HTML on the server, you need to add a package to your application called meteorhacks:ssr. Once you have the package installed, you can store plain HTML files inside your /private directory and then convert them later, passing any data to replace handlebars helpers like {{name}} in the process.
For example, here is some code I have used to send a welcome email when new users register:
import { SSR } from 'meteor/meteorhacks:ssr';
const getHTMLForEmail = (templateName, data) => {
SSR.compileTemplate(templateName, Assets.getText(`email/templates/${templateName}.html`));
return SSR.render(templateName, data);
};
const sendEmail = (emailAddress, html) => {
if (emailAddress.includes('#')) {
const emailData = {
to: emailAddress,
from: 'Test Email <hello#test.io>',
subject: 'Welcome aboard, team matey!',
html,
};
Meteor.defer(() => Email.send(emailData));
}
};
export const sendWelcomeEmail = (user, profile) => {
let email;
if (user.services.facebook) {
email = user.services.facebook.email;
} else if (user.services.google) {
email = user.services.google.email;
}
const data = {
email,
name: profile && profile.name ? profile.name : '',
url: 'www.google.com',
};
const html = getHTMLForEmail( 'welcome-email', data );
sendEmail(data.email, html);
};
You will find the following two articles from Meteor Chef very useful (also shows how the html email template looks like):
Using the email package
Sign up with email verification

phonegap submit form, how to send to my email

I am building simple phonegap android app.
i make simple html form with few input fields (Name, Last name, Question).
I want that when user fill input fields (Name, Last name, Question) and click Submit to send to my email address. Just that.
Do you have any idea how to do that with phonegap?
Thank you
You could do it easily by using php or .net (as your selection) with AJAX Call
Just Create One HTML page which display form to User for filling up data and send it.
Here I saw you how I done with PHP (Use phpmailer. for more, visit : http://phpmailer.worxware.com/index.php?pg=examplebmail)
HTML Form
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<form action="#!" method="post">
<input type = "text" name="cname" />
<input type = "number" name="cnumber" />
<input type = "email" name="cemail" />
<input type = "submit" value="Submit" onclick="UpdateRecord()" />
</form>
<script>
function UpdateRecord()
{
// Social Links
GolbalURL = "http://www.yourserverpathtophpfile.com";
var cname = $("[name='cname']").val();
var cnumber = $("[name='cnumber']").val();
var cemail = $("[name='cemail']").val();
jQuery.ajax({
type: "POST",
url: GolbalURL+"sendemail.php",
data: "cname="+ cname+"& cnumber="+ cnumber+"& cemail="+ cemail,
dataType: "html",
cache: false,
success: function(response)
{
alert("Email Sent");
}
});
}
</script>
</body>
</html>
Sendmail.php
<?php
$cname = $_REQUEST['cname'];
$cnumber = $_REQUEST['cnumber'];
$cemail = $_REQUEST['cemail'];
require_once('class.phpmailer.php');
$mail = new PHPMailer(); // defaults to using php "mail()"
$body = "Name : ".$cname."Number : ".$cnumber."Email : ".$cemail;
$mail->SetFrom($cemail, $cname);
$address = "youremail#id.com";
$mail->AddAddress($address, "Your Name");
$mail->Subject = "Your Subject";
$mail->AltBody = "To view the message, please use an HTML compatible email viewer!"; // optional, comment out and test
$mail->MsgHTML($body);
if(!$mail->Send()) {
echo "Mailer Error: " . $mail->ErrorInfo;
} else {
echo "Message sent!";
}
?>
Do not forgot to upload your dynamic files to server and give it permissions. Or You can also call device's default mail application from code, check PHONEGAP EMAIL COMPOSER
GIT Link Of Email Compo.
https://github.com/katzer/cordova-plugin-email-composer/blob/172605ee12e58d5e5809e4e031b3b96cead143ac/README.md
You can do using Cordova EmailComposer Plugin for Android . Add this function on your submit button click. For installation follow these steps .
https://github.com/katzer/cordova-plugin-email-composer
function emailComposer(){
window.plugin.email.isServiceAvailable(
function (isAvailable) {
if(isAvailable){
window.plugin.email.open({
to: [''],
cc: [''],
bcc: [''],
subject: '',
body: ''
});
}else{
alert('Service is not available');
}
}
);
}
**JQUERY - CALL PHP SCRIPT TO POST DATA**
var ajax_call = serviceURL;
var form_data = $('#form').serialize();
$.ajax({
type: "POST",
url: ajax_call,
data: form_data,
dataType: "json",
success: function(response) {
//called when successful
},
error: function(e) {
//called when there is an error
//console.log(e.message);
}
});
Examples
There are plugins to compose emails, but it won't send it automatically. You really need to use a back end service to handle this for you. You can setup your own using any app language (PHP, ColdFusion, etc), or consider a service like WuFoo perhaps.

send an email using a template - grails

I want to send an email using a template. I want to have a GSP file where i could style it, and send the email. Currently the send mail function is as follows:
def sendEmail(){
mailService.sendMail {
to "email","**email**"
from "email"
subject "Hi"
body 'Hi'
}
}
in my config.groovy file
grails {
mail {
host = "smtp.gmail.com"
port = 465
username = "email"
password = "pwd"
props = ["mail.smtp.auth":"true",
"mail.smtp.socketFactory.port":"465",
"mail.smtp.socketFactory.class":"javax.net.ssl.SSLSocketFactory",
"mail.smtp.socketFactory.fallback":"false"]
}
}
I went through another Stack Overflow post on this: Where should i add the mail templates ? is it in the views folder ?
sendMail{
multipart true
to "[hidden email]"
subject "Subject goes here"
html g.render( template: '/emails/mailTemplate')
inline 'springsourceInlineImage', 'image/jpg', new File('./web-app/images/springsource.png')
}
UPDATE
I TREID ADDING A mailTemplate.gsp UNDER EMAILS/ BUT IT DIDNT WORK.
ERROR I GOT Template not found for name [/emails/mailTemplate] and path [/emails/_mailTemplate.gsp]
You can use groovyPageRenderer.render() to parse your email. Below, an example:
class MailingService {
def groovyPageRenderer
def mailService
def yourFunction(User user) {
def content = groovyPageRenderer.render(view: '/mails/myTemplate')
mailService.sendMail {
to user.email
from "email#test.com"
subject "MySubject"
html(content)
}
}
}
In this case, the template is here: /views/mails/MyTemplateFile.gsp
Hope this helps.
Edit:
And the render could be used with a model. Example:
groovyPageRenderer.render(view:'/mails/myTemplate',model:[user:user])
Edit2:
I forgot to add the mailService in my first reply
well, you can try this code...
mailService.sendMail {
to user.email
from "email#test.com"
subject "MySubject"
body(view:'/emails/mailTemplate', model: [a:A])
}
here mailTemplate.gsp is in view/emails. In body of mail service you can use render syntax.
then add '<%# page contentType="text/html" %>' in top of mailTemplate.gsp
Well looking at your code, everything looks good enough.
html g.render(template : '/path/to/template')
should render your template and it will become the body of your mail message.
Have you made sure that you made your template as _template. Since all the gsp's that start with (_) are only considered as a template.
You should also make all the styling(css) inline so that it gets rendered without errors in all mail providers.