spring-integration-mail接收器邮件,用于在Spring Boot 时读取电子邮件程序

ntjbwcob  于 2023-01-04  发布在  Spring
关注(0)|答案(1)|浏览(382)

我从git复制了代码来读取邮件,我累了很多,但在运行应用程序时,在控制台中遇到了如下错误。请帮助我解决这个问题:
enter image description here
这是我的申请表。这里我指定的用户名和密码是正确的

logging:
  level:
    root: INFO
    org.ygaros: DEBUG

spring:
  mail:
    username: arunofficial302@gmail.com
    password: ***************
    properties:
      protocol: imaps
      host: imap.gmail.com
      port: 993

这是我的配置文件:

package com.htc.mailOperation.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.InboundChannelAdapter;
import org.springframework.integration.annotation.Poller;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.config.EnableIntegration;
import org.springframework.integration.mail.ImapMailReceiver;
import org.springframework.integration.mail.MailReceiver;
import org.springframework.integration.mail.MailReceivingMessageSource;
import org.springframework.messaging.Message;

import com.htc.mailOperation.service.MailReceiverService;

import javax.mail.internet.MimeMessage;

@Configuration
@EnableIntegration
public class MailConfig {

    private static final Logger log = LoggerFactory.getLogger(MailConfig.class);
    
    @Autowired
    private MailReceiverService receiverService;

    @Value("${spring.mail.username}")
    private String USERNAME;

    @Value("${spring.mail.password}")
    private String PASSWORD;

    @Value("${spring.mail.properties.port}")
    private int IMAP_PORT;

    @Value("${spring.mail.properties.protocol}")
    private String IMAP_PROTOCOL;

    @Value("${spring.mail.properties.host}")
    private String IMAP_HOST;

    /*
        Define a channel where we send and get the messages (mails in this example).
        MessageSource is sending messages to this channel.
        DirectChannel is a SubscribableChannel.
     */
    @Bean("incomingEmailsChannel")
    public DirectChannel defaultChannel() {
        DirectChannel directChannel = new DirectChannel();
        directChannel.setDatatypes(MimeMessage.class);
        return directChannel;
    }
    @Bean
    public MailReceiver imapMailReceiver() {
        String url = String.format(
                "%s://%s:%s@%s:%s/INBOX", IMAP_PROTOCOL, USERNAME, PASSWORD, IMAP_HOST, IMAP_PORT
        );
        log.debug("IMAP url: {}", url.replace(PASSWORD, "x".repeat(8)));

        ImapMailReceiver imapMailReceiver = new ImapMailReceiver(url);
        imapMailReceiver.setShouldMarkMessagesAsRead(true);
        imapMailReceiver.setShouldDeleteMessages(false);
        /*
            Attach content to message because by default the MimeMessage
            doesn't contain content body.
         */
        imapMailReceiver.setSimpleContent(true);
        //imapMailReceiver.setMaxFetchSize(1);

        return imapMailReceiver;
    }

    /*
      Provide MessageSource of Mails as spring integration Messages from ImapMailReceiver to be sent
      through incomingEmailsChannel.
      Poller with defined rate at which the messages are pushed to the channel
      (if there are any) every 5 sec.
   */
    @Bean
    @InboundChannelAdapter(
            channel = "incomingEmailsChannel",
            poller = @Poller(fixedDelay = "5000")

    )
    public MailReceivingMessageSource mailMessageSource(MailReceiver mailReceiver) {
        return new MailReceivingMessageSource(mailReceiver);

    }

    /*
        Connect (subscribe) to incomingEmailsChannel channel and provide method to
        handle each individual messages.
     */
    @ServiceActivator(inputChannel = "incomingEmailsChannel")
    public void receive(Message<MimeMessage> message) {
        receiverService.handleReceivedMail(message.getPayload());
    }
}

这是我的服务文件:

package com.htc.mailOperation.service;

import org.apache.commons.mail.util.MimeMessageParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.FileSystemResource;
import org.springframework.stereotype.Service;

import javax.activation.DataSource;
import javax.mail.internet.MimeMessage;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

@Service
public class MailReceiverService {

    private static final Logger log = LoggerFactory.getLogger(MailReceiverService.class);
    private static final String ATTACHMENTS_FOLDER_STORE = "data";

    public void handleReceivedMail(MimeMessage receivedMessage){
        try {
            MimeMessageParser mimeMessageParser = new MimeMessageParser(receivedMessage);
            mimeMessageParser.parse();

            logMail(mimeMessageParser);
            saveAttachments(mimeMessageParser);

            /*
                To delete downloaded email
                Setting those flag will delete messages only when we use folder.close(true);
            message.setFlag(Flags.Flag.DELETED, true);
             */
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    private void logMail(MimeMessageParser mimeMessageParser) throws Exception {
        log.debug("From: {} To: {} Subject: {}",
                mimeMessageParser.getFrom(), mimeMessageParser.getTo(), mimeMessageParser.getSubject());
        log.debug("Mail content: {}", mimeMessageParser.getPlainContent());

    }

    private void saveAttachments(MimeMessageParser parser){
        List<DataSource> attachments = parser.getAttachmentList();
        log.debug("Email has {} attachment files", attachments.size());
        attachments.forEach(dataSource -> {
            String fileName = dataSource.getName();
            if(fileName != null && fileName.length() > 0){
                String rootDirPath = new FileSystemResource("").getFile().getAbsolutePath();

                createDirectoryIfNotExists(rootDirPath);

                String attachmentFilePath = rootDirPath +
                        File.separator +
                        ATTACHMENTS_FOLDER_STORE +
                        File.separator +
                        fileName;
                File attachmentFile = new File(attachmentFilePath);

                log.info("Attachment file saved to: {}", attachmentFilePath);

                try(
                        InputStream in = dataSource.getInputStream();
                        OutputStream out = new FileOutputStream(attachmentFile)
                        ){
                    copyStream(in, out);
                }catch(IOException e){
                    log.error("Failed to save file.", e);
                }
            }
        });
    }

    private void createDirectoryIfNotExists(String directoryPath) {
        Path of = Path.of(directoryPath);
        if (!Files.exists(of)) {
            try {
                Files.createDirectories(of);
            } catch (IOException e) {
                log.error("An error: {} on creating: {}", e, directoryPath);
            }
        }
    }

    private void copyStream(InputStream in, OutputStream out) throws IOException {
        byte[] buffer = new byte[8192]; //just my standard base buffer
        int readByteCount;
        while(-1 != (readByteCount = in.read(buffer))){
            out.write(buffer, 0, readByteCount);
        }
    }
}

有人能帮我一下吗?

qlfbtfca

qlfbtfca1#

在生成url之前,您需要将用户名和密码转换为x-www-form-urlencoded格式。例如:

...
public MailReceiver imapMailReceiver() {
   USERNAME = URLEncoder.encode(USERNAME, StandardCharsets.UTF_8.name());
   PASSWORD = URLEncoder.encode(PASSWORD, StandardCharsets.UTF_8.name());
   String url = String.format(
                "%s://%s:%s@%s:%s/INBOX", IMAP_PROTOCOL, USERNAME, PASSWORD, IMAP_HOST, IMAP_PORT
        );
...

相关问题