JavaMail IMAP sur SSL assez lente en Vrac de l'extraction de plusieurs messages
Je suis en train d'essayer d'utiliser JavaMail pour obtenir des e-mails à partir des serveurs IMAP (Gmail et autres). Fondamentalement, mon code fonctionne: j'ai en effet peut obtenir les en-têtes, le contenu du corps et ainsi de suite. Mon problème est le suivant: lorsque l'on travaille sur un serveur IMAP (sans SSL), il prend essentiellement en 1-2ms pour traiter un message. Quand je vais sur un serveur IMAPS (donc avec SSL, comme Gmail) je atteindre environ 250m/message. J'ai SEULEMENT de mesurer les temps lors du traitement des messages (la connexion, la poignée de main et ne sont PAS pris en compte).
Je sais que, depuis cela est SSL, les données sont cryptées. Cependant, le temps de déchiffrement doit pas être si important que cela, devrait-il?
J'ai essayé la plus grande ServerCacheSize valeur, une plus grande connectionpoolsize, mais je suis sérieusement à court d'idées. La personne aux prises avec ce problème? Résolu l'on pourrait espérer?
Ma crainte est que l'API JavaMail utilise une connexion différente à chaque fois qu'il récupère un mail depuis le serveur IMAPS (concernant les frais généraux pour l'établissement de liaisons...). Si oui, est-il un moyen de remplacer ce comportement?
Voici mon code (bien que tout à fait standard) appelé à partir de la méthode main() de la classe:
public static int connectTest(String SSL, String user, String pwd, String host) throws IOException,
ProtocolException,
GeneralSecurityException {
Properties props = System.getProperties();
props.setProperty("mail.store.protocol", SSL);
props.setProperty("mail.imaps.ssl.trust", host);
props.setProperty("mail.imaps.connectionpoolsize", "10");
try {
Session session = Session.getDefaultInstance(props, null);
//session.setDebug(true);
Store store = session.getStore(SSL);
store.connect(host, user, pwd);
Folder inbox = store.getFolder("INBOX");
inbox.open(Folder.READ_ONLY);
int numMess = inbox.getMessageCount();
Message[] messages = inbox.getMessages();
for (Message m : messages) {
m.getAllHeaders();
m.getContent();
}
inbox.close(false);
store.close();
return numMess;
} catch (MessagingException e) {
e.printStackTrace();
System.exit(2);
}
return 0;
}
Merci d'avance.
- Remarque: la Chaîne SSL est soit "imap" ou "imap". Aussi, j'ai lu la question stackoverflow.com/questions/2538481/javamail-performance mais ils ont essayé sur un serveur IMAPS qui n'est pas Gmail et je suis toujours à obtenir les mêmes résultats.
- Est-ce possible avec d'autres clients (Thunderbird, Outlook, qu'est-ce-avez-vous) sur le même IMAP/IMAPS serveur? Dans ce cas, ce ne serait pas votre code de la faute, et plutôt un problème de serveur.
- Comment puis-je mesurer le temps Thunderbird prend pour importer les messages? (nous sommes dans la mme zone...). Il charge tous les dossiers en moins de 20 secondes (mais je ne sais pas si il a obtenu seulement quelques informations et reçoit le reste, quand je clique sur le message).
- Hmm, c'est un peu gênant, oui. Je crois qu'il a une sorte de journal des opérations (désactivé par défaut), mais la résolution sera en quelques secondes tout au plus. Vous pouvez configurer la TUBERCULOSE pour télécharger les messages (il ne reçoit que des en-têtes par défaut), puis à mesurer l'ensemble de la boîte de réception, ce qu'il faudrait au moins savoir si il faut < 1 sec, ou de plusieurs secondes.
- Quel est votre système d'exploitation?
- Ubuntu 11.04 @Piskvor: encore travailler sur ces journaux pour vous donner une réponse précise.
- Ok, désolé pour l'attente (Thunderbird journal de ne pas activer l'horodatage par défaut...). Pour un message, le contenu du corps récupérée sous thunderbird, voici les horodateurs: 2011-11-30 08:47:10.360004 UTC (commencer à chercher) ... 2011-11-30 08:47:10.360922 UTC - -1989445888[7f5b7e04a150]: 7dcba000:imap.googlemail.com:S-BOÎTE de réception:STREAM:FERMETURE: Normal Message de Téléchargement de Fin de Flux 2011-11-30 08:47:10.385466 UTC - -1989445888[7f5b7e04a150]: ReadNextLine [stream=8cdc70e0 nb=56 needmore=0] Donc, soit 25ms ou 1ms pour obtenir le corps du message...
Vous devez vous connecter pour publier un commentaire.
après beaucoup de travail, et de l'aide aux personnes à JavaMail, la source de cette "lenteur" est à partir de l'EXTRACTION de comportement dans l'API. En effet, comme pjaol dit, nous revenons sur le serveur à chaque fois que nous avons besoin d'info (un en-tête, ou le contenu du message) pour un message.
Si FetchProfile nous permet de nous en vrac chercher de l'information d'en-tête, ou des drapeaux, pour de nombreux messages, à obtenir des contenus de messages multiples, n'est PAS directement possible.
Heureusement, nous pouvons écrire notre propre commande IMAP pour éviter cette "limitation" (il a été fait de cette façon pour éviter des erreurs de mémoire insuffisante: récupérer tous les messages dans la mémoire en une seule commande peut être très lourd).
Voici mon code:
la getContents(MimeMessage mm, int i) la fonction est un classique de la fonction de manière récursive imprime le contenu du message dans un fichier (de nombreux exemples disponibles sur le net).
Pour éviter les erreurs de mémoire, j'ai simplement mis un maxDocs et maxSize limite (ce qui a été fait de manière arbitraire et peut probablement être améliorée!) utilisé comme suit:
Ne pas qu'ici je suis en utilisant les numéros de message, qui est instable (ces changements si les messages sont effacés du serveur). Une meilleure méthode serait d'utiliser des Liquides! Ensuite, vous pouvez modifier la commande à partir de RÉCUPÉRER UID FETCH.
Espérons que cette aide!
Response[] r = protocol.command("FETCH", args); Response response = r[r.length - 1];
j'ai besoin de marquer le message comme lu lorsque je suis seule à recevoir des courriels à partir de certaine personne. J'ai cette logique enContents.getContents(mm, i)
méthode. Je suis en train de définirmessage.setFlag(Flags.Flag.SEEN, false);
pour le message en premier, puis si la condition est satisfaite alors marquer le message comme lu. Sa ne fonctionne pas. Toutes les mises à jour j'ai besoin de faireVous avez besoin d'ajouter un FetchProfile à la boîte de réception avant de parcourir les messages.
Message est un paresseux chargement de l'objet, il sera de retour sur le serveur pour chaque message et pour chaque
champ qui n'est pas fourni avec le profil par défaut.
par exemple,
Si vous souhaitez afficher comme une boîte de réception d'inscription de dire à Partir de, sous réserve, Envoyé, Attachement, etc.., vous utilisez quelque chose comme ce qui suit
Espère que ça aide.
Le temps total comprend le temps requis dans les opérations de chiffrement. Les opérations cryptographiques besoin d'un hasard semoir. Il existe différents aléatoire semis implémentations qui fournissent des bits aléatoires pour l'utilisation de la cryptographie. Par défaut, Java utilise /dev/urandom et cela est spécifié dans votre java.sécurité comme ci-dessous:
Sur Windows, java utilise Microsoft CryptoAPI de semences fonctionnalité qui a généralement pas de problèmes. Cependant, unix et linux, Java, par défaut, utilise /dev/random aléatoire du semis. Et les opérations de lecture sur /dev/random parfois bloquer et prend beaucoup de temps. Si vous utilisez les *nix plates-formes puis le temps passé dans ce seraient comptabilisés dans le temps global.
Depuis, je ne sais pas ce que la plateforme que vous utilisez, je ne peux pas vous dire que ce pourrait être votre problème. Mais si vous êtes, alors ce pourrait être l'une des raisons pour lesquelles vos opérations prennent du temps. Une solution pourrait être d'utiliser /dev/urandom au lieu de /dev/random que votre aléatoires semoir, qui ne bloque pas. Ceci peut être spécifié avec le système de la propriété "de java.de sécurité.egd". Par exemple,
La spécification de ce système de la propriété remplace la securerandom.réglage de source en java.fichier de sécurité. Vous pouvez lui donner un essai. Espérons que cela aide.