I'm working in a Java EE webApplication and I hope to send emails to my clients.
So I add mail.jar and activation.jar and I tried this simple code:
import java.util.Properties;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class SendHTML {
static Properties mailServerProperties;
static Session getMailSession;
static MimeMessage generateMailMessage;
public static void main(String args[]) throws AddressException, MessagingException {
generateAndSendEmail();
System.out.println("\n\n ===> Your Java Program has just sent an Email successfully. Check your email..");
}
public static void generateAndSendEmail() throws AddressException, MessagingException {
//Step1
System.out.println("\n 1st ===> setup Mail Server Properties..");
mailServerProperties = System.getProperties();
mailServerProperties.put("mail.smtp.port", "587"); // TLS Port
mailServerProperties.put("mail.smtp.auth", "true"); // Enable Authentication
mailServerProperties.put("mail.smtp.starttls.enable", "true"); // Enable StartTLS
System.out.println("Mail Server Properties have been setup successfully..");
//Step2
System.out.println("\n\n 2nd ===> get Mail Session..");
getMailSession = Session.getDefaultInstance(mailServerProperties, null);
generateMailMessage = new MimeMessage(getMailSession);
generateMailMessage.addRecipient(Message.RecipientType.TO, new InternetAddress("Recipient#gmail.com"));
generateMailMessage.addRecipient(Message.RecipientType.CC, new InternetAddress("Recipient#gmail.com"));
generateMailMessage.setSubject("Greetings from me..");
String emailBody = "Test email by me JavaMail API example. " + "<br><br> Regards, <br>Admin";
generateMailMessage.setContent(emailBody, "text/html");
System.out.println("Mail Session has been created successfully..");
//Step3
System.out.println("\n\n 3rd ===> Get Session and Send mail");
Transport transport = getMailSession.getTransport("smtp");
// Enter your correct gmail UserID and Password
transport.connect("smtp.gmail.com", "myusername#gmail.com", "mypassword");
transport.sendMessage(generateMailMessage, generateMailMessage.getAllRecipients());
transport.close();
}
}
So Step1 and Step2 work successfully, but Step3 generate an Authentication exception:
1st ===> setup Mail Server Properties..
Mail Server Properties have been setup successfully..
2nd ===> get Mail Session..
Mail Session has been created successfully..
3rd ===> Get Session and Send mail
Exception in thread "main" javax.mail.AuthenticationFailedException
at javax.mail.Service.connect(Service.java:264)
at javax.mail.Service.connect(Service.java:134)
at entity.SendHTML.generateAndSendEmail(SendHTML.java:53)
at entity.SendHTML.main(SendHTML.java:24)
Please can someone help me to fixe the problem ?
First, there is nothing named "JEE", you meant "Java EE".
If you're using Java EE, you shouldn't need mail.jar and activation.jar, they're already part of every Java EE server.
You're going to want to read these JavaMail FAQ entries on common mistakes and how to debug JavaMail applications.
AuthenticationFailedException means the server doesn't like your username and password.
You're probably running into the problem described here.
Related
I have a question regarding Restful services
I need to upload CSV files to an AWS server. I am registered with account.
First I need to obtain an access token and use that to upload the files. I have not coded anything yet, trying to understand the best approach, I so hope to use Camel-Rest-DSL. It is required to communicate with JSON. But, the authentication part has me stuck, I’m pretty sure it uses OAuth2 auth, RestFul web service and JSON, this should just be a client, I was looking at WSS4J for JAX-RS OAuth2 but I don’t know.
I’ve done it with postman, this is the scenario. The username and password are fictional
*Get Access Token
uses POST verb
requires Token Request URL
uses Basic Auth requires Username = Client ID of tenant ( needs to be encoded base64 )
HEADER parm Content-Type = x-www-form-urlencoded
Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + encoded Client ID
Access Token body - grant_type, username, password
Body = username = 5c0642fe-a495-44db-93f7-67034556fa2c061_ingestor
password = 154f0252d166f27b5e21ef171b03212a79f41a0daf3
grant_type = password
#returns the access_token as JSON
POST or upload files
uses POST verb
requires Ingestion URL UploadURL
UploadURL=https://apm-ts-query-svc-prd.app-api.aws-usw02-pr.something.io/v2/time_series/
UploadFolder=upload
headers =
key Authentication "Bearer + access Token" (from request access token above)
key Tenant = TenantUUID
key X-GE-CsvFormat = ODB
# Body
form-data
key file=file
# POST DATA
headers content-type application/json
authorization: "" + token
tenant: "" + tenant
My environment
Jboss Fuse 6.3-310
Karaf version 2.4.0.redhat-630310
JVM
Java Virtual Machine Java HotSpot(TM) 64-Bit Server VM version 25.162-
b12
Version 1.8.0_162
Vendor Oracle Corporation
Operating system
Name Linux version 2.6.32-696.20.1.el6.x86_64
I can't use OAuth2/SAML assertions so I will simply request a token and cache it and use it later. this is my test code
#Override
public void configure() throws Exception {
//Configure the Rest Web Service Component transport to use a REST implementation
restConfiguration() //Configures the REST DSL to use a specific REST implementation
.component("jetty") //Specifies the Camel component to use as the REST transport
.host("localhost") //The hostname to use for exposing the REST service
.port("8282") //The port number to use for exposing the REST service JMX tooling
.scheme("https") //The protocol to use for exposing the REST service
.contextPath("/oauth/token") //Sets a leading context path for the REST services
.bindingMode(RestBindingMode.json) //Enables binding mode for JSON
.jsonDataFormat("json-jackson") //Specifies the component that Camel uses to implement the JSON data format
.dataFormatProperty("prettyPrint", "true"); //set arbitrary properties on the underlying data format component
//Configure the Rest Endpoint
rest("/oauth") //Defines a service using the REST DSL. Each of the verb clauses are terminated by a to() keyword,
//which forwards the incoming message to an endpoint
.post("/token")
.produces("application/json")
.consumes("application/json")
.type(TokenEntities.class)
.route()
.routeId("Get Auth Token Route")
.autoStartup(true)
.id("Get Auth Token Service")
.description("Get Authorization Token")
.process(new UAARequestTokenProcessor())
.to("https://d1e53858-2903-4c21-86c0-95edc7a5cef2.pager-uaa.run.aws-usw02-pr.ice.pager.io/oauth/token")
.to("log:logger?showBody=true")
.to("direct:accessToken")
.endRest();
//Define the Route - from() Defines a regular Camel route.
from("direct:accessToken").to("log:logger?showBody=true"); }
public class UAARequestTokenProcessor implements Processor {
private static final Logger LOG = LoggerFactory.getLogger(UAARequestTokenProcessor.class);
private String clientId = "myClientID";
private String userName = "myUserName";
private String password = "myPassword";
#Override
public void process(Exchange exchange) throws Exception {
LOG.info("Processing UAA token request for " + clientId + " and " + userName);
Message msg = exchange.getOut(); //create outbound message exchange
StringBuilder authHeader = new StringBuilder("Basic ");
authHeader.append(Base64.getEncoder().encodeToString((clientId + ":").getBytes("UTF_8")));
String body = String.format("grant_type=password&username=%s&password=%s",
URLEncoder.encode(userName, "UTF-8"), //Translates a string into x-www-form-urlencoded format
URLEncoder.encode(password, "UTF-8"));
msg.setHeader(Exchange.CONTENT_TYPE, "MediaType.APPLICATION_FORM_URLENCODE");
msg.setHeader("Authorization", authHeader.toString());
msg.setBody(body);
}
}
We have a requirement of enabling universal link in our application. We have a java based web application(spring) and a iOS app. To enable universal link as per apple we need to create a json file apple-app-association-file and host this file in the server.
Now java web app is deployed in tomcat in windows server and apche 2.4 is being used as web server. Please let me know how to host the apple-app-association-file in the tomcat or web server or inside the war file(inside the code), we are using maven structure.
according to docs, we need to remove the file extentsion and file should be access as below:
url of web app: https://xyz.example.com
where xyz.example.com is mapped to a web app which is there in webapp folder in tomcat.(localhost:8080/webApp)
apple-app-association-file to be accessed as: https://xyz.example.com/apple-app-association-file
now as the extension is not there how can i host it.Do i need to make the code changes and treated it as servle request. Even if i do so it wont be a good idea to execute a servet just to access a file
Also, it's also important that the file is served with the correct MIME-type, for Universal Links it can be served as application/json. How to set mime type in tomcat or java web app(spring)
First rename file to apple-app-site-association.json, then write next Spring configuration:
#EnableWebMvc
public class WebClientConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/.well-known/*")
.addResourceLocations("/path/to/your/static/resources")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
#Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
if (resourcePath.equals("apple-app-site-association")) {
return location.createRelative("apple-app-site-association.json");
}
return super.getResource(resourcePath, location);
}
});
}
}
As described here: developer.apple.com
You can place the file at the root of your server or in the .well-known subdirectory.
Then the file will be served with the correct MIME-type "application/json" and accessed as: https://xyz.example.com/.well-known/apple-app-association-file
The Solution from pITer Simonov works for me! But i had to add the root path
inside
< servlet-mapping > (in web.xml)
like this:
< url-pattern >/</url-pattern >
After that, the resource handler work fine!
I did it with a standard REST controller + endpoint.
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
#RestController
#RequestMapping("/.well-known")
#Slf4j
public class WebClientConfig {
#GetMapping(value = "/apple-app-site-association",
produces = MediaType.APPLICATION_JSON_VALUE)
public String addResourceHandlers() {
String json = "";
InputStream inputStream = getClass().getResourceAsStream("/apple-app-association.json");
try(InputStream stream = inputStream) {
json = StreamUtils.copyToString(stream, Charset.forName("UTF-8"));
} catch (IOException ioe) {
log.error("Apple app association could not be retrieved! iOS app will be impacted. Error: " +
ioe.getMessage());
}
return json;
}
}
Note: the apple-app-asociation.json file is under src/main/resources
I tried to code a 'Hello world' type of exercise to learn Spring Boot support for OAuth2, and the minimum required configuration.
Components:
Authorization server
webapp, which will call the auth server to authenticate the user, and will greet him
Expected flow:
I open the webapp
I get redirected to auth server
I login to auth server
I approve the requested scope
I get redirected back to webapp
I see a greeting (webapp should fetch my username from auth server)
The last point fails with 401:Could not obtain access token.
Last redirect link is http://localhost:9001/ui/login?code=wcXMG4&state=JEEYqC
Am I too naive to assume that the below code&configuration should suffice for my expected flow?
Auth server:
#SpringBootApplication
#EnableAuthorizationServer
#EnableResourceServer
#RestController
public class AuthServer {
public static void main(String[] args) {
SpringApplication.run(AuthServer.class);
}
#GetMapping("/whois")
Principal whois(Principal principal) {
return principal;
}
}
Auth server properties:
server.port=9000
server.contextPath=/sso
security.user.name=joe
security.user.password=password
security.oauth2.client.clientId=SOMEAPP
security.oauth2.client.clientSecret=SECRET
security.oauth2.client.authorized-grant-types=authorization_code,refresh_token,password
security.oauth2.client.scope=read
security.oauth2.resource.userInfoUri=http://localhost:9000/sso/whois
Webapp:
#SpringBootApplication
#EnableOAuth2Sso
#RestController
public class UiServer {
public static void main(String[] args) {
SpringApplication.run(UiServer.class);
}
#GetMapping("/")
String helloWorld(Principal principal) {
return "Yay, auth server provided identity, you are " + principal;
}
}
Webapp properties:
server.port=9001
server.contextPath=/ui
security.oauth2.client.client-id=SOMEAPP
security.oauth2.client.client-secret=SECRET
security.oauth2.client.accessTokenUri=http://localhost:9000/sso/oauth/access_token
security.oauth2.client.userAuthorizationUri=http://localhost:9000/sso/oauth/authorize
security.oauth2.resource.user-info-uri=http://localhost:9000/sso/whois
After spinning up with debug on, it turns out that security.oauth2.client.accessTokenUri is incorrect.
The right endpoint is not .../oauth/access_token, but .../oauth/token.
Probably the tutorial I was looking at used outdated uri.
With that fix, this minimum config does what's expected of it, so I'll close the question.
The real fun begins when you try to customize it, bypassing the defaults; to me it seems that spring oauth still has major bugs, and requires hacky/unexpected approach to work around them in few use cases.
I am writing a bulk email program using the JavaMail api. I have a Microsoft Exhange server which I am trying to send the emails in to. When I run my program I get the following error:
**com.sun.mail.smtp.SMTPTransport.issueSendCommand(SMTPTransport.java:2057)
at com.sun.mail.smtp.SMTPTransport.finishData(SMTPTransport.java:1862)
at com.sun.mail.smtp.SMTPTransport.sendMessage(SMTPTransport.java:1100)
at javax.mail.Transport.send0(Transport.java:195)
at javax.mail.Transport.send(Transport.java:124)
at SendEmail.postMail(SendEmail.java:100)
at EmailGenerator.main(EmailGenerator.java:52)**
The part of my code trying to send the message is as follows:
Properties props = new Properties();
props.put("mail.smtp.host", email_server);
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.auth", true);
class EmailAuthenticator extends Authenticator {
String user;
String pw;
EmailAuthenticator (String FROM, String PASSWORD)
{
super();
this.user = FROM;
this.pw = PASSWORD;
}
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(user, pw);
}
}
Session session = Session.getInstance(props, new EmailAuthenticator(USER, PASSWORD));
session.setDebug(debug);
System.out.println("Session created");
.. CREATED MESSAGE HERE...
Transport transport = session.getTransport("smtp");
transport.connect(exchange_server,user,password);
transport.send(msg);
transport.close();
I wonder am I missing some configuration on the Exchange server side, or is an issue with my code?
OK I figured out where I was going wrong here and am posting up the answer incase anybody else can get some value out of it. I had the following line of code:
props.put("mail.smtp.auth", true);
This was telling my application that it needed to authenticate to the SMTP server, when in fact it didnt. This was causing my application from logging into the SMTP server and sending the email and thus producing the error message. Setting this property to false or not having this line of code fixed the issue for me. This line of code is only necessary for SMTP servers that require you to login, which my Exchange server didnt.
Is it possible to use NServiceBus in an application without having any input queues?
Reason is, I have an ASP.NET MVC application that sends messages to other applications when something happens (e.g. a new user registers). The web application never recieves any responses or other messages and therefore I would like not to bog the app. with the msmq peeking which throws an exception every second.
That is supported, just remove the msmstranport config section and all should be fine. This works against 2.0.1281.0 (net4) version of NServiceBus with no app.config present
using NServiceBus;
namespace SendOnlyEndpoint.Custom
{
public class Program
{
static void Main(string[] args)
{
var bus = Configure.With()
.DefaultBuilder()
.XmlSerializer()
.MsmqTransport()
.UnicastBus()
.CreateBus()
.Start();
bus.Send("SendOnlyDestination",new TestMessage());
}
}
public class TestMessage : IMessage
{
}
}
More info on send only endpoints here
I would try not configuring an input queue. Bus.Send will use an internal outbound queue to send messages.