Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codenameone.developerguide.backend.mail;

import com.codename1.backend.annotations.Component;
import com.codename1.backend.mail.Mail;
import com.codename1.backend.mail.MailException;
import com.codename1.backend.mail.MailSender;
import com.codename1.backend.mvc.Model;
import com.codenameone.developerguide.backend.orders.Order;

import java.io.IOException;

@Component
public class Receipts {
private final MailSender mail;

public Receipts(MailSender mail) {
this.mail = mail;
}

// tag::backend-mail-template[]
public void shipped(Order order, String email) throws IOException {
Model model = new Model()
.addAttribute("customer", order.customer)
.addAttribute("orderId", Long.valueOf(order.id));
mail.send(Mail.to(email)
.subject("Your order shipped")
.template("mail/shipped", model)
.build());
}
// end::backend-mail-template[]

// tag::backend-mail-attach[]
public void invoice(Order order, String email, byte[] pdf, byte[] logo) throws IOException {
mail.send(Mail.to(email)
.cc("accounts@example.com")
.replyTo("billing@example.com")
.subject("Invoice " + order.id)
.html("<img src=\"cid:logo\" alt=\"Acme\"><p>Your invoice is attached.</p>")
.inline("logo", "image/png", logo)
.attach("invoice-" + order.id + ".pdf", "application/pdf", pdf)
.header("X-Order", String.valueOf(order.id))
.build());
}
// end::backend-mail-attach[]

// tag::backend-mail-now[]
public boolean sendCode(String email, String code) throws IOException {
try {
mail.sendNow(Mail.to(email)
.subject("Your code")
.text("Your code is " + code)
.build());
return true;
} catch (MailException refused) {
// isPermanent(): the server will never take this mail.
return false;
}
}
// end::backend-mail-now[]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codenameone.developerguide.backend.mail;

import com.codename1.backend.DataSource;
import com.codename1.backend.annotations.Component;
import com.codename1.backend.annotations.Transactional;
import com.codename1.backend.mail.Mail;
import com.codename1.backend.mail.MailSender;

import java.io.IOException;

// tag::backend-mail-send[]
@Component
public class Signup {
private final DataSource db;
private final MailSender mail;

public Signup(DataSource db, MailSender mail) {
this.db = db;
this.mail = mail;
}

@Transactional
public void register(String name, String email) throws IOException {
db.execute("INSERT INTO accounts (name, email) VALUES (?, ?)",
new Object[] {name, email});
// Staged in this transaction, sent once it commits.
mail.send(Mail.to(email)
.subject("Welcome, " + name)
.text("Your account is ready. Sign in at https://example.com/login")
.build());
}
}
// end::backend-mail-send[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codenameone.developerguide.backend.mail;

import com.codename1.backend.annotations.Autowired;
import com.codename1.backend.mail.Mail;
import com.codename1.backend.mail.MailSender;
import com.codename1.backend.test.BackendTest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

// tag::backend-mail-test[]
@BackendTest(properties = "cn1.mail.from=Acme <no-reply@example.com>")
class SignupTest {
@Autowired
private Signup signup;

@Autowired
private MailSender mail;

@BeforeEach
void emptyInbox() throws Exception {
mail.clearSent();
}

@Test
void aNewAccountIsWelcomed() throws Exception {
signup.register("Ada", "ada@example.com");

assertEquals(1, mail.sent().size());
Mail welcome = mail.sent().get(0);
assertEquals("ada@example.com", welcome.getTo().get(0));
assertEquals("Welcome, Ada", welcome.getSubject());
assertTrue(welcome.getText().contains("https://example.com/login"));
}
}
// end::backend-mail-test[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* Copyright (c) 2012, Codename One and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Codename One designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Codename One through http://www.codenameone.com/ if you
* need additional information or have any questions.
*/
package com.codenameone.developerguide.backend.security;

import com.codename1.backend.DataSource;
import com.codename1.backend.annotations.Bean;
import com.codename1.backend.annotations.Configuration;
import com.codename1.backend.mail.MailSender;
import com.codename1.backend.security.Customizer;
import com.codename1.backend.security.HttpSecurity;
import com.codename1.backend.security.SecurityFilterChain;
import com.codename1.backend.security.core.userdetails.JdbcUserDetailsManager;
import com.codename1.backend.security.crypto.PasswordEncoder;
import com.codename1.backend.security.mail.EmailVerificationService;
import com.codename1.backend.security.mail.JdbcOneTimeTokenRepository;
import com.codename1.backend.security.mail.JdbcVerifiedEmailRepository;
import com.codename1.backend.security.mail.OneTimeTokenService;
import com.codename1.backend.security.mail.PasswordResetService;
import com.codename1.backend.security.mfa.EmailCodeService;
import com.codename1.backend.security.mfa.JdbcEmailCodeRepository;

import java.io.IOException;

/** The Backend security chapter's examples of the flows that send mail. */
@Configuration
public class MailSecurityConfig {
// tag::backend-security-reset[]
@Bean
OneTimeTokenService oneTimeTokens(DataSource dataSource) {
return new OneTimeTokenService(new JdbcOneTimeTokenRepository(dataSource));
}

@Bean
PasswordResetService passwordReset(OneTimeTokenService tokens, MailSender mail,
JdbcUserDetailsManager users, PasswordEncoder encoder) {
return new PasswordResetService(tokens, mail, users, users, encoder);
}

@Bean
SecurityFilterChain web(HttpSecurity http) {
http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.formLogin(Customizer.withDefaults())
.passwordReset(Customizer.withDefaults());
return http.build();
}
// end::backend-security-reset[]

// tag::backend-security-verify[]
@Bean
EmailVerificationService emailVerification(OneTimeTokenService tokens, MailSender mail,
DataSource dataSource) {
return new EmailVerificationService(tokens, mail,
new JdbcVerifiedEmailRepository(dataSource));
}

@Bean
SecurityFilterChain shop(HttpSecurity http, EmailVerificationService verification) {
http.authorizeHttpRequests(auth -> auth
.requestMatchers("/checkout/**").access(verification.verified())
.anyRequest().authenticated())
.formLogin(Customizer.withDefaults())
.emailVerification(Customizer.withDefaults());
return http.build();
}
// end::backend-security-verify[]

// tag::backend-security-verify-send[]
void afterSignup(EmailVerificationService verification, String username, String email)
throws IOException {
verification.send(username, email, "https://example.com/verify-email");
}
// end::backend-security-verify-send[]

// tag::backend-security-email-code[]
@Bean
EmailCodeService emailCodes(DataSource dataSource, MailSender mail) {
return new EmailCodeService(new JdbcEmailCodeRepository(dataSource), mail);
}

@Bean
SecurityFilterChain account(HttpSecurity http) {
http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
.formLogin(Customizer.withDefaults())
.mfa(Customizer.withDefaults());
return http.build();
}
// end::backend-security-email-code[]
}
5 changes: 5 additions & 0 deletions docs/demos/backend/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@ cn1.session.store=kv
# ...and a broker for messages.
cn1.messaging.url=kafka://kafka-1:9092,kafka-2:9092
# end::backend-scale-out[]

# tag::backend-mail-config[]
cn1.mail.url=smtp://${SMTP_USER}:${SMTP_PASSWORD}@smtp.example.com:587
cn1.mail.from=Acme <no-reply@example.com>
# end::backend-mail-config[]
9 changes: 9 additions & 0 deletions docs/demos/backend/src/main/snippets/mail-shipped.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- tag::backend-mail-template-html[] -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p>Hello <span th:text="${customer}">customer</span>,</p>
<p>Order <strong th:text="${orderId}">1</strong> is on its way.</p>
</body>
</html>
<!-- end::backend-mail-template-html[] -->
Loading
Loading