What configurations should I do to enable Exchange Mailbox reading through javax Mail?

Marco Aurélio Cabral 0 Reputation points
2023-03-03T01:25:54.3233333+00:00

I've been trying to adapt a old java code to connect in a online exchange mailbox.

Here is the code based on this totorial


	public static void main(String[] args) throws MessagingException, NoSuchProviderException {
		final var tokenProvider = new RopcTokenProvider();

		final var accessToken = tokenProvider.getAccessToken();

		final var user = "******@contoso.com";
		final var host = "outlook.office365.com";

		final Properties props = new Properties();
		props.put("mail.debug", "true");
		props.put("mail.imaps.debug", "true");
		props.put("mail.store.protocol", "imaps");
		props.put("mail.imaps.auth.plain.disable", true);
		props.put("mail.imaps.port", 993);
		props.put("mail.imaps.ssl.enable", "true");
		props.put("mail.imaps.starttls.enable", "true");
		props.put("mail.imaps.auth.mechanisms", "XOAUTH2");

		Session session = Session.getInstance(props);
		Store store = session.getStore("imaps");
		store.connect(host, user, accessToken);
		final var inbox = store.getFolder("INBOX");
	}

	private static interface TokenProvider {
		String getAccessToken();
	}

	private static class RopcTokenProvider implements TokenProvider {

		@Override
		public String getAccessToken() {
			final var tennantId = "tennant-id";
			final var clientId = "clientId";
			final var clientSecret = "clientSecret";
			final var url = "https://login.microsoftonline.com/%s/oauth2/v2.0/token";

			final var headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);


			final var map = new LinkedMultiValueMap<String, String>();
			map.add("client_id", clientId);
			map.add("client_secret", clientSecret);
			map.add("scope", "https://outlook.office365.com/.default");
			map.add("grant_type", "client_credentials");

			final var request = new HttpEntity<MultiValueMap<String, String>>(map, headers);

			final var restTemplate = new RestTemplate();

			final var oAuthTokenDTOResponseEntity = restTemplate.postForEntity(
					String.format(url, tennantId),
					request,
					String.class
			);

			final var body = oAuthTokenDTOResponseEntity.getBody();

			try {
				return new ObjectMapper().readValue(body, OAuthTokenDTO.class).getAccessToken();
			} catch (IOException e) {
				throw new RuntimeException(e);
			}
		}
	}


	private static class OAuthTokenDTO {
		@JsonProperty("token_type")
		private String tokenType;
		@JsonProperty("expires_in")
		private String expiresIn;
		@JsonProperty("ext_expires_in")
		private String extExpiresIn;
		@JsonProperty("access_token")
		private String accessToken;

		public String getTokenType() {
			return tokenType;
		}

		public void setTokenType(String tokenType) {
			this.tokenType = tokenType;
		}

		public String getExpiresIn() {
			return expiresIn;
		}

		public void setExpiresIn(String expiresIn) {
			this.expiresIn = expiresIn;
		}

		public String getExtExpiresIn() {
			return extExpiresIn;
		}

		public void setExtExpiresIn(String extExpiresIn) {
			this.extExpiresIn = extExpiresIn;
		}

		public String getAccessToken() {
			return accessToken;
		}

		public void setAccessToken(String accessToken) {
			this.accessToken = accessToken;
		}
	}

My application is configured in azure with these permissions setpermissions

But when I execute the code I have this problem with IMAP authentication

DEBUG: JavaMail version 1.6.2
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: getProvider() returning javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle]
DEBUG IMAPS: mail.imap.fetchsize: 16384
DEBUG IMAPS: mail.imap.ignorebodystructuresize: false
DEBUG IMAPS: mail.imap.statuscachetimeout: 1000
DEBUG IMAPS: mail.imap.appendbuffersize: -1
DEBUG IMAPS: mail.imap.minidletime: 10
DEBUG IMAPS: enable STARTTLS
DEBUG IMAPS: closeFoldersOnStoreFailure
DEBUG IMAPS: trying to connect to host "outlook.office365.com", port 993, isSSL true
* OK The Microsoft Exchange IMAP4 service is ready. [ZwBQZQATIOy==]
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG IMAPS: AUTH: PLAIN
DEBUG IMAPS: AUTH: XOAUTH2
DEBUG IMAPS: protocolConnect login, host=outlook.office365.com, user=contoso@contoso, password=<non-null>
DEBUG IMAPS: AUTHENTICATE XOAUTH2 command trace suppressed
DEBUG IMAPS: AUTHENTICATE XOAUTH2 command result: A1 NO AUTHENTICATE failed.
Exception in thread "main" javax.mail.AuthenticationFailedException: AUTHENTICATE failed.
	at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:732)
	at javax.mail.Service.connect(Service.java:366)
	at javax.mail.Service.connect(Service.java:246)
	at Another.main(Another.java:39)
Exchange Online
Exchange Online
A Microsoft email and calendaring hosted service.
6,182 questions
Exchange | Exchange Server | Development
{count} votes

1 answer

Sort by: Most helpful
  1. Andy David - MVP 157.8K Reputation points MVP Volunteer Moderator
    2023-03-03T12:30:40.4733333+00:00

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.