Importar contato do Gmail programaticamente em Java

O Gmail do Google está entre os serviços de e-mail mais populares e usados. O Gmail oferece vários recursos, além de apenas enviar e receber e-mails, como agendas, bate-papos etc. Em alguns casos, pode ser necessário conectar-se ao Gmail e importar contatos programaticamente de seus aplicativos. Para conseguir isso, este artigo mostra como importar contatos do Gmail usando Java. Além disso, abordaremos como acessar contatos em um grupo de e-mail específico.

API Java para importar contatos do Gmail

Aspose.Email for Java é uma API poderosa para criar aplicativos de cliente de e-mail. Além disso, suporta trabalhar com o Gmail, como acessar contatos, calendários, compromissos, etc. Usaremos esta API para acessar e importar contatos de contas do Gmail. Você pode baixar a API ou instalá-la usando as seguintes configurações do Maven.

Repositório:

<repository>
    <id>AsposeJavaAPI</id>
    <name>Aspose Java API</name>
    <url>http://repository.aspose.com/repo/</url>
</repository>

Dependência:

<dependency>
    <groupId>com.aspose</groupId>
    <artifactId>aspose-email</artifactId>
    <version>22.2</version>
    <classifier>jdk16</classifier>
</dependency>

Importar contatos do Gmail em Java

Antes de começar, você precisa criar um projeto no Google Developer Console, que permitirá a execução do código. Para criar um, você pode seguir este guia.

Agora, crie uma classe auxiliar chamada GoogleOAuthHelper para cuidar da autenticação de uma conta do Gmail. Além disso, crie uma classe chamada OAuthUser para armazenar informações do usuário. A seguir está a implementação completa de ambas as classes.

public class OAuthUser {
        String email;
        String clientId;
        String clientSecret;
        String refreshToken;
    }
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.xml.bind.DatatypeConverter;

/**
 * <p>
 * Console de desenvolvedores https://console.developers.google.com/projectselector/apis/credentials?pli=1 
 * Documentação https://developers.google.com/identity/protocols/OAuth2InstalledApp
 * </p>
 */
class GoogleOAuthHelper {
    public static final String AUTHORIZATION_URL = "https://accounts.google.com/o/oauth2/v2/auth";
    public static final String TOKEN_REQUEST_URL = "https://oauth2.googleapis.com/token";
    public static final String REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";
    public static final String REDIRECT_TYPE = "code";
    public static final String SCOPE = "https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcalendar" // Calendar
            + "+https%3A%2F%2Fwww.google.com%2Fm8%2Ffeeds%2F" // Contacts
            + "+https%3A%2F%2Fmail.google.com%2F"; // IMAP & SMTP

    static String createCodeChalange() {
        String verifierStr = UUID.randomUUID().toString() + "-" + UUID.randomUUID().toString();
        System.out.println("Code Verifier: " + verifierStr);

        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("SHA-256");
        } catch (NoSuchAlgorithmException e) {
            throw new IllegalAccessError(e.getMessage());
        }
        byte[] hash = digest.digest(verifierStr.getBytes(StandardCharsets.UTF_8));
        String base64Hash = DatatypeConverter.printBase64Binary(hash);

        base64Hash = base64Hash.split("=")[0];
        base64Hash = base64Hash.replace('+', '-').replace('/', '_');
        return base64Hash;
    }

    static String getAuthorizationCodeUrl(OAuthUser acc) {
        return getAuthorizationCodeUrl(acc, SCOPE, REDIRECT_URI, REDIRECT_TYPE);
    }

    static String getAuthorizationCodeUrl(OAuthUser acc, String scope, String redirectUri, String responseType) {
        System.out.println("---------------------------------------------------------");
        System.out.println("------------- OAuth 2.0 AuthorizationCodeUrl -------------");
        System.out.println("---------------------------------------------------------");
        System.out.println("Login: " + acc.email);
        String codeChallenge = createCodeChalange();

        String state = urlEncode(UUID.randomUUID().toString());
        String approveUrl = AUTHORIZATION_URL + "?client_id=" + acc.clientId + "&redirect_uri=" + redirectUri + "&response_type=" + responseType + "&scope=" + scope
                + "&code_challenge=" + codeChallenge + "&code_challenge_method=S256&state=" + state;

        System.out.println("Approve Url: " + approveUrl);
        return approveUrl;
    }

    static String urlEncode(String value) {
        try {
            return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
        } catch (UnsupportedEncodingException e) {
            throw new IllegalAccessError(e.getMessage());
        }
    }

    static String urlDecode(String value) {
        try {
            return URLDecoder.decode(value, StandardCharsets.UTF_8.toString());
        } catch (UnsupportedEncodingException e) {
            throw new IllegalAccessError(e.getMessage());
        }
    }

    static String getAccessTokenByAuthCode(String authorizationCode, String codeVerifier, OAuthUser user) {
        String encodedParameters = "client_id=" + urlEncode(user.clientId) + "&client_secret=" + urlEncode(user.clientSecret) + "&code=" + urlEncode(authorizationCode)
                + "&code_verifier=" + codeVerifier + "&redirect_uri=" + urlEncode(REDIRECT_URI) + "&grant_type=authorization_code";
        System.out.println("---------------------------------------------------------");
        System.out.println("------------- OAuth 2.0 AccessTokenByAuthCode -------------");
        System.out.println("---------------------------------------------------------");
        System.out.println("Authorization code: " + authorizationCode);

        String result = "";
        Map<String, String> token = geToken(encodedParameters);
        for (String key : token.keySet()) {
            System.out.println(key + ": " + token.get(key));
            if (key.equals("refresh_token")) {
                result = token.get(key);
            }
        }

        System.out.println("---------------------------------------------------------");

        return result;
    }

    static String getAccessTokenByRefreshToken(OAuthUser user) {
        String encodedParameters = "client_id=" + urlEncode(user.clientId) + "&client_secret=" + urlEncode(user.clientSecret) + "&refresh_token=" + urlEncode(user.refreshToken)
                + "&grant_type=refresh_token";
        System.out.println("---------------------------------------------------------");
        System.out.println("----------- OAuth 2.0 AccessTokenByRefreshToken -----------");
        System.out.println("---------------------------------------------------------");
        System.out.println("Login: " + user.email);

        String result = "";
        Map<String, String> token = geToken(encodedParameters);
        for (String key : token.keySet()) {
            System.out.println(key + ": " + token.get(key));
            if (key.equals("access_token")) {
                result = token.get(key);
            }
        }

        System.out.println("---------------------------------------------------------");

        return result;
    }

    static Map<String, String> geToken(String encodedParameters) {
        try {
            HttpURLConnection connection = (HttpURLConnection) new URL(TOKEN_REQUEST_URL).openConnection();
            connection.setRequestMethod("POST");

            byte[] requestData = encodedParameters.getBytes(StandardCharsets.UTF_8);

            connection.setUseCaches(false);
            connection.setDoInput(true);
            connection.setDoOutput(true);
            connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            connection.setRequestProperty("Content-Length", "" + requestData.length);

            final OutputStream st = connection.getOutputStream();
            try {
                st.write(requestData, 0, requestData.length);
            } finally {
                st.flush();
                st.close();
            }

            connection.connect();

            if (connection.getResponseCode() >= HttpURLConnection.HTTP_BAD_REQUEST) {
                throw new IllegalAccessError("Operation failed: " + connection.getResponseCode() + "/" + connection.getResponseMessage() + "\r\nDetails:\r\n{2}"
                        + readInputStream(connection.getErrorStream()));
            }

            String responseText = readInputStream(connection.getInputStream());

            Map<String, String> result = new HashMap<String, String>();
            System.out.println(responseText);
            String[] strs = responseText.replace("{", "").replace("}", "").replace("\"", "").replace("\r", "").replace("\n", "").split(",");
            for (String sPair : strs) {
                String[] pair = sPair.split(":");
                String name = pair[0].trim().toLowerCase();
                String value = urlDecode(pair[1].trim());
                result.put(name, value);
            }

            return result;
        } catch (IOException e) {
            throw new IllegalAccessError(e.getMessage());
        }
    }

    static String readInputStream(InputStream is) {
        if (is == null)
            return "";

        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder result = new StringBuilder();
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                result.append(line);
            }
        } catch (IOException e) {
            // ignorar
        }
        return result.toString();
    }
}

Importar contatos de uma conta do Gmail

A seguir estão as etapas para importar contatos de uma conta do Gmail em Java.

  • Crie um objeto da classe OAuthUser e inicialize-o com email, ID do cliente e segredo do cliente.
  • Crie dois objetos de string para armazenar o código de autorização e o verificador de código.
  • Obtenha o token de atualização e o token de acesso.
  • Obtenha uma instância da classe GmailClient em um objeto IGmailClient usando o método GmailClient.getInstance(String, String).
  • Leia contatos em uma matriz usando o método IGmailClient.getAllContacts().
  • Faça um loop pela matriz para acessar cada contato.

O exemplo de código a seguir mostra como importar contatos do Gmail de uma conta em Java.

OAuthUser user = new OAuthUser();

// Definir clientId, clientSecret e email 
user.clientId = "<<clientID>>"; 
user.clientSecret = "<<clientSecret>>"; 
user.email = "<<email>>";

// Você precisa recuperar AuthorizationCode manualmente com AuthorizationCodeUrl gerado
// Definir código de autorização
String authorizationCode = "<<authCode>>";

// Copie o verificador de código da saída da etapa anterior
// Definir codeVerifier
String codeVerifier = "<<codeVerifier>>";

// Obter token de atualização
String refreshToken = GoogleOAuthHelper.getAccessTokenByAuthCode(authorizationCode, codeVerifier, user);
user.refreshToken = refreshToken;

// Obter token de acesso
String accessToken = GoogleOAuthHelper.getAccessTokenByRefreshToken(user);

// Usar token de acesso na API
IGmailClient client = GmailClient.getInstance(accessToken, user.email);

Contact[] contacts = client.getAllContacts();
for (Contact contact : contacts)
	System.out.println(contact.getDisplayName() + ", " + contact.getEmailAddresses().get_Item(0));

Importar contatos do Gmail de um grupo

Você também pode acessar os contatos de um grupo de e-mail específico no Gmail seguindo as etapas abaixo.

  • Siga as etapas mencionadas na seção anterior para inicializar o IGmailClient.
  • Chame IGmailClient.getAllGroups() para obter grupos em um objeto ContactGroupCollection.
  • Filtre os grupos necessários com base no título.
  • Acesse contatos de um grupo usando o método IGmailClient.getContactsFromGroup(String).
  • Faça um loop pela matriz para acessar cada contato.

O exemplo de código a seguir mostra como importar contatos de um grupo específico do Gmail em Java.

OAuthUser user = new OAuthUser();

// Definir clientId, clientSecret e email 
user.clientId = "<<clientID>>"; 
user.clientSecret = "<<clientSecret>>"; 
user.email = "<<email>>";

// Você precisa recuperar AuthorizationCode manualmente com AuthorizationCodeUrl gerado
// Definir código de autorização
String authorizationCode = "<<authCode>>";

// Copie o verificador de código da saída da etapa anterior
// Definir codeVerifier
String codeVerifier = "<<codeVerifier>>";

// Obter token de atualização
String refreshToken = GoogleOAuthHelper.getAccessTokenByAuthCode(authorizationCode, codeVerifier, user);
user.refreshToken = refreshToken;

// Obter token de acesso
String accessToken = GoogleOAuthHelper.getAccessTokenByRefreshToken(user);

// Usar token de acesso na API
IGmailClient client = GmailClient.getInstance(accessToken, user.email);

// Buscar contatos de um grupo específico
ContactGroupCollection groups = client.getAllGroups();
GoogleContactGroup group = null;
for (GoogleContactGroup g : groups) {
	if ("TestGroup".equals(g.getTitle())) {
		group = g;
	}
}

// Recuperar contatos do grupo
if (group != null) {
	Contact[] contacts2 = client.getContactsFromGroup(group.getId());
	for (Contact con : contacts2)
		System.out.println(con.getDisplayName() + "," + con.getEmailAddresses().get_Item(0).toString());
}

Obtenha uma licença de API gratuita

Você pode obter uma licença temporária gratuita para usar o Aspose.Email para Java sem limitações de avaliação.

Conclusão

Neste artigo, você aprendeu como importar contatos do Gmail de uma conta programaticamente em Java. Além disso, você viu como acessar contatos de um determinado grupo de e-mail no Gmail. Além disso, você pode explorar a documentação para ler mais sobre o Aspose.Email para Java. Além disso, você pode fazer suas perguntas através do nosso fórum.

Veja também