java邮件发送工具

邮件发送

            log.info("查询添加的信息,userIDs->{},useraccounts->{},csPersonIds->{},csPersonAccounts->{}", userIds, userAccounts, csPersonIds, csPersonAccounts);
            //这只是一个文案
            String textContent = String.format("由%1$s(%2$s)发起的%3$s已经成功发给您",
                   发送人姓名, 发送人账户, 发送项目名称);
            try {
                //发送邮箱
                if (!CollectionUtils.isEmpty(userIds)) {
                //发送到对方,点击查看转跳地址
                    String redirectPath = spUrl + "?path=" + URLEncoder.encode((appRecordMain.getId()==null ? "/home" : "/review/detail?id="+appRecordMain.getId()), "UTF-8");
                    String content = "<html lang='zh-CN'><head ><meta charset='utf-8'></head><body>"
                            + textContent + "<a href='" + redirectPath + "'>【点此查看】</a></body></html>";
                     //userIds -》用户ID,csPersonIds-》抄送人IDS(没有可以不写),appRecordMain.getAppName()-》项目名称,content-》文案内容
                    noticeService.sengEmail(userIds, csPersonIds, appRecordMain.getAppName(), content);
                }
            } catch (UnsupportedEncodingException e) {
                log.error(e.getMessage(), e);
                throw new RuntimeException(e.getMessage());
            }

public boolean sengEmail(List<Long> toEmailUsers, List<Long> ccEmailUsers, String title, String content) {
        try {
            // 日志输出
            log.info("发送的用户id:" + toEmailUsers + " , 抄送人:" + ccEmailUsers + ", 发送标题:" + title + ", 发送内容:" + content);
            // 获取所有要发送的目标邮件和用户信息 普通发送和抄送
            Map<String, String> toEmailAccountMap = getMailMap(toEmailUsers);
            Map<String, String> ccMap = getMailMap(ccEmailUsers);
            EmailUtils.sendEmil(toEmailAccountMap, ccMap, title, content);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 用户id获取用户信息,封装成要发送的邮箱
     *
     * @param userIds
     * @return
     */
    private Map<String, String> getMailMap(List<Long> userIds) {
        List<SysUserInfoResCO> sysUserInfoResCOS = new ArrayList<>();
         //一个一个查询放到map中
        for (Long userId : userIds) {
        //通过userId 查出来用户信息,比如 用户账号,姓名,邮件
            SingleResponse<SysUserInfoResCO> response = userClientFeignServiceI.qryUserInfoByUserAccount(null, Math.toIntExact(userId));
            SysUserInfoResCO data = response.getData();
            sysUserInfoResCOS.add(data);
        }
        Map<String, String> map = new HashMap<>();
        for (SysUserInfoResCO sysUserInfoResCO : sysUserInfoResCOS) {
            if (null == sysUserInfoResCO.getUserEmail()) {
                continue;
            }
            map.put(sysUserInfoResCO.getCnName(), sysUserInfoResCO.getUserEmail());
        }
        log.info("获取map中的用户信息=>{}" , map);
        return map;
    }

发送邮件工具-EmailUtils

//发送邮件工具
 //@Value("${mail.fromEmailAccount}")
 //@Value("${mail.fromEmailPassword}")
 //@Value("${mail.formEmailSMTPHOST}")
// 这个三个在配置文件中写死即可。
@Component
public class EmailUtils {

    /**
     * 发信人的Email地址
     */
    private static String fromEmailAccount ;
    /**
     * 发信人的称呼
     */
    private static String fromEmailShow;
    /**
     * 发信人的Email邮箱密码
     */
    private static String fromEmailPassword ;
    /**
     * 收信人的Email地址
     */
    private static String toEmailAccount;
    /**
     * 收信人的称呼
     */
    private static String toEmailShow;
    /**
     * 发信人邮箱的SMTP服务器地址
     */
    private static String formEmailSMTPHOST ;
    /**
     * 发信人邮箱的POP3服务器地址
     */
    private static String formEmailPOP3HOST;
    /**
     * 发信人邮箱的IMAP服务器地址
     */
    private static String formEmailIMAPHOST;
    /**
     * 连接邮件服务器的参数配置
     */
    private static Properties properties;
    /**
     * 连接邮件服务器的参数配置
     */
    private static Boolean isSMTP;
    /**
     * 是否是SSL连接
     */
    private static Boolean isSSL;
    /**
     * 邮件主题
     */
    private static String emailSubject;
    /**
     * 邮件内容
     */
    private static String emailContent;
    /**
     * 用于添加到邮件中的图片
     */
    private static Map<String, File> imageFilesMap = new HashMap<String, File>();
    ;
    /**
     * 用于添加到邮件中的附件
     */
    private static List<File> attachContentsList = new ArrayList<File>();
    /**
     * 邮件发送日期
     */
    private static Date emailSendDate;
    /**
     * 邮件编码
     */
    private final static String EMAIL_CHARSET = "UTF-8";
    /**
     * 邮件内容编码
     */
    private final static String CONTENT_CHARSET = "text/html;charset=UTF-8";

    // 初始化
    private static void initEmail() {
        // 默认配置一些邮件信息
        // 默认配置发信人的Email地址
        if (EmailUtils.fromEmailAccount == null) {
            // 发信人的Email地址(这是我注册的一个测试用的邮箱)
            EmailUtils.fromEmailAccount = "blh@cdtrust.com";
            // 发信人的Email邮箱密码
            EmailUtils.fromEmailPassword = "Qwelkj123";
            // 发件人的服务器地址
            EmailUtils.formEmailSMTPHOST = "smtp.exmail.qq.com";
        }
        // 默认配置发信人称呼
        if (EmailUtils.fromEmailShow == null) {
            // 发信人称呼位邮箱前缀
            EmailUtils.fromEmailShow = EmailUtils.fromEmailAccount.substring(0, EmailUtils.fromEmailAccount.indexOf("@"));
        }
        // 默认配置收信人的称呼
        if (EmailUtils.toEmailShow == null) {
            if (EmailUtils.toEmailAccount != null) {
                // 收信人的称呼为收件人邮箱前缀
                EmailUtils.toEmailShow = EmailUtils.toEmailAccount.substring(0, EmailUtils.toEmailAccount.indexOf("@"));
            }
        }
        // 默认使用SMTP协议
        if (EmailUtils.isSMTP == null) {
            EmailUtils.isSMTP = true;
        }
        // 默认不使用SSL安全认证协议
        if (EmailUtils.isSSL == null) {
            EmailUtils.isSSL = false;
        }
        // 默认邮件内容为 Hello World
        if (EmailUtils.emailContent == null) {
            EmailUtils.emailContent = "<h1>Hello,World!</h1>";
        }
        // 默认邮件主题为内容前两个字
        if (EmailUtils.emailSubject == null) {
            // 选择21是因为默认邮件内容长度是21
            if (EmailUtils.emailContent.length() >= 21) {
                EmailUtils.emailSubject = EmailUtils.emailContent.substring(0, 21);
            } else {
                EmailUtils.emailSubject = EmailUtils.emailContent;
            }
        }
        // 默认邮件发送日期为当前时间
        if (EmailUtils.emailSendDate == null) {
            EmailUtils.emailSendDate = new Date();
        }

        // 实例化Properties
        properties = new Properties();

        // 如果是SMTP协议
        if (isSMTP) {
            properties = setSMTPProps(properties);
        }

        // 如果为 SSL 安全认证(连接失败, 要求 SSL 安全连接时使用)
        if (isSSL) {
            properties = setSSLProps(properties);
        }
    }

    /**
     * SMTP协议
     *
     * @param properties
     * @return
     */
    private static Properties setSMTPProps(Properties properties) {
        // 指定默认消息传输协议。该
        // Session方法getTransport()返回实现此协议的Transport对象。默认情况下,返回配置文件中的第一个传输提供程序。
        String transportProtocolKEY = "mail.transport.protocol";
        // 指定协议的邮件服务器的主机名。覆盖mail.host属性。
        String smtpHostKEY = "mail.smtp.host";
        // 指定协议的邮件服务器的端口号。如果未指定,则使用协议的默认端口号。(一般不用设置)
        String smtpPortKEY = "mail.smtp.port";
        // 使用指定的协议连接到邮件服务器时要使用的用户名。覆盖mail.user属性。(一般不用设置)
        String smtpUserKEY = "mail.smtp.user";
        // 如果为true,则尝试使用AUTH命令认证用户。默认为false。
        String smtpAuthKEY = "mail.smtp.auth";

        // 设置协议为smtp
        String transportProtocolVALUE = "smtp";
        properties.setProperty(transportProtocolKEY, transportProtocolVALUE);
        // 发件人的邮箱的 SMTP 服务器地址
        properties.setProperty(smtpHostKEY, formEmailSMTPHOST);
        // 需要请求认证
        properties.setProperty(smtpAuthKEY, "true");
        return properties;
    }

    /**
     * SSL 安全认证
     *
     * @param properties
     * @return
     */
    private static Properties setSSLProps(Properties properties) {
        // 如果为 SSL 安全认证(连接失败, 要求 SSL 安全连接时使用)
        // 如果set,则指定实现该javax.net.SocketFactory接口的类的名称 。此类将用于创建SMTP套接字。
        String socketFactoryClassKEY = "mail.smtp.socketFactory.class";
        // 如果设置为true,则无法使用指定的套接字工厂类创建套接字将导致使用java.net.Socket该类创建套接字。默认为true。
        String socketFactoryFallbackKEY = "mail.smtp.socketFactory.fallback";
        // 指定使用指定套接字工厂时要连接的端口。如果未设置,将使用默认端口。
        String socketFactoryPortKEY = "mail.smtp.socketFactory.port";

        // SMTP 服务器的端口 (非 SSL 连接的端口一般默认为 25, 可以不添加, 如果开启了 SSL 连接,需要改为对应邮箱的 SMTP
        // 服务器的端口
        // QQ邮箱的SMTP(SLL)端口为465或587
        String sslSmtpPortVALUE = "465";
        // 设置端口号
        properties.setProperty(socketFactoryPortKEY, sslSmtpPortVALUE);
        // 指定javax.net.ssl.SSLSocketFactory 。此类将用于创建SMTP套接字。
        String socketFactoryClassVALUE = "javax.net.ssl.SSLSocketFactory";
        // 指定javax.net.ssl.SSLSocketFactory用于创建SMTP套接字。
        properties.setProperty(socketFactoryClassKEY, socketFactoryClassVALUE);
        // 设置使用指定的套接字工厂类创建套接字
        properties.setProperty(socketFactoryFallbackKEY, "false");
        return properties;
    }


    /**
     * 发送邮件(收件人是多个)
     *
     * @param fromEmailAccount   发送人邮箱
     * @param fromEmailPassword  发送人邮箱密码
     * @param toEmailAccountMap  收件人map
     * @param formEmailSMTPHOST  发送人邮箱SMTP服务器地址
     * @param emailSubject       邮件主题
     * @param emailContent       邮件内容
     * @param imageFilesMap      邮件图片集
     * @param attachContentsList 邮件附件集
     * @throws UnsupportedEncodingException
     * @throws
     */
    public static void sendEmil(String fromEmailAccount, String fromEmailPassword, Map<String, String> toEmailAccountMap, Map<String, String> ccMap, String formEmailSMTPHOST, String emailSubject, String emailContent, Map<String, File> imageFilesMap, List<File> attachContentsList) throws UnsupportedEncodingException, MessagingException {
        sendEmil(fromEmailAccount, null, fromEmailPassword, null, null, formEmailSMTPHOST, null, null, emailSubject, emailContent, null, toEmailAccountMap, ccMap, imageFilesMap, attachContentsList);
    }


    /**
     * 发送邮件(收件人是多个)
     *
     * @param toEmailAccountMap 收件人map
     * @param ccMap             收件人map
     * @param emailContent      邮件内容
     * @throws UnsupportedEncodingException
     * @throws
     */
    public static void sendEmil(Map<String, String> toEmailAccountMap, Map<String, String> ccMap, String emailSubject, String emailContent) throws UnsupportedEncodingException, MessagingException {
        sendEmil(fromEmailAccount, null, fromEmailPassword, null, null, formEmailSMTPHOST, null, null, emailSubject, emailContent, null, toEmailAccountMap, ccMap, null, null);
    }

    //发送邮件
    public static void sendEmil(String fromEmailAccount, String fromEmailShow, String fromEmailPassword, String toEmailAccount, String toEmailShow, String formEmailSMTPHOST, Boolean isSMTP, Boolean isSSL, String emailSubject, String emailContent, Date emailSendDate, Map<String, String> toEmailAccountMap, Map<String, String> ccMap, Map<String, File> imageFilesMap, List<File> attachContentsList) throws UnsupportedEncodingException, MessagingException {
        // 发信人的Email地址
        EmailUtils.fromEmailAccount = fromEmailAccount;
        // 发信人称呼
        EmailUtils.fromEmailShow = fromEmailShow;
        // 发信人的Email邮箱密码
        EmailUtils.fromEmailPassword = fromEmailPassword;
        // 收信人的Email地址
        EmailUtils.toEmailAccount = toEmailAccount;
        // 收信人的称呼
        EmailUtils.toEmailShow = toEmailShow;
        // 发件人的服务器地址
        EmailUtils.formEmailSMTPHOST = formEmailSMTPHOST;
        // 是否使用SMTP协议
        EmailUtils.isSMTP = isSMTP;
        // 是否使用SSL安全认证协议
        EmailUtils.isSSL = isSSL;
        // 邮件主题
        EmailUtils.emailSubject = emailSubject;
        // 邮件内容
        EmailUtils.emailContent = emailContent;
        // 邮件图片集
        EmailUtils.imageFilesMap = imageFilesMap;
        // 邮件附件集
        EmailUtils.attachContentsList = attachContentsList;
        // 邮件发送日期
        EmailUtils.emailSendDate = emailSendDate;
        // 1. 配置用于连接邮件服务器的参数
        initEmail();
        // 2. 根据配置创建会话对象, 用于和邮件服务器交互
        Session session = Session.getDefaultInstance(properties);
        // 设置为debug模式, 可以查看详细的发送 log
        session.setDebug(true);
        // 3. 创建一封邮件
        MimeMessage message = createMimeMessage(session, toEmailAccountMap, ccMap);
        //还可以保存邮件到本地
        //OutputStream out = new FileOutputStream("MyEmail.eml");
        // message.writeTo(out);
        // out.flush();out.close();
        // 4. 根据 Session 获取邮件传输对象
        Transport transport = session.getTransport();
        // 5. 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错
        transport.connect(EmailUtils.fromEmailAccount, EmailUtils.fromEmailPassword);
        // 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人,抄送人, 密送人
        transport.sendMessage(message, message.getAllRecipients());
        // 7. 关闭连接
        transport.close();

    }

    /**
     * main方法用于测试工具类
     *
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        // 测试拥有多个收信人
        Map<String, String> emails = new HashMap<String, String>();
        //map的key是收件人称呼,value是收件人邮箱地址
//        emails.put("chentiefeng007", "baolonghu1212@163.com");
        emails.put("1234", "zgb@cdtrust.com");
        emails.put("2lj;", "132@163.com");
//		emails.put("chentiefeng521", "chentiefeng521@163.com");

        //拥有多个收信人
        Map<String, String> emails2 = new HashMap<String, String>();
        //map的key是收件人称呼,value是收件人邮箱地址
//        emails.put("chentiefeng007", "chentiefeng007@126.com");
//		emails.put("chentiefeng521", "chentiefeng521@163.com");
        //发送邮件
        sendEmil(emails, emails2, "XXX来电", "content");
    }

    /**
     * 创建邮件信息
     *
     * @param session
     * @param toEmailAccountMap
     * @param ccMap
     * @return
     * @throws UnsupportedEncodingException
     * @throws
     */
    private static MimeMessage createMimeMessage(Session session, Map toEmailAccountMap, Map ccMap) throws UnsupportedEncodingException, MessagingException {
        // 1. 创建一封邮件
        MimeMessage message = new MimeMessage(session);
        // 2. From: 发件人
        message.setFrom(new InternetAddress(EmailUtils.fromEmailAccount, EmailUtils.fromEmailShow, EMAIL_CHARSET));
        // 3. To: 收件人(可以增加多个收件人)当toEmailAccountMap不为空时,是多个收件人
        //为了防止出现554 DT:SPM 126,在发送之前,给自己抄一份
//        message.setRecipient(RecipientType.CC, new InternetAddress(EmailUtils.fromEmailAccount, EmailUtils.fromEmailShow, EMAIL_CHARSET));
        if (toEmailAccountMap != null) {
            if (toEmailAccountMap.size() > 0) {
                Set<String> emailShows = toEmailAccountMap.keySet();
                String[] emailShowsStr = new String[emailShows.size()];
                emailShows.toArray(emailShowsStr);
                for (int i = 0; i < emailShowsStr.length; i++) {
                    if (i == 0) {
                        //RecipientType.TO:普通发送
                        //RecipientType.CC:抄送
                        //RecipientType.BCC:密送
                        message.setRecipient(RecipientType.TO, new InternetAddress(toEmailAccountMap.get(emailShowsStr[i]).toString(), emailShowsStr[i], EMAIL_CHARSET));
                    } else {
                        message.addRecipient(RecipientType.TO, new InternetAddress(toEmailAccountMap.get(emailShowsStr[i]).toString(), emailShowsStr[i], EMAIL_CHARSET));
                    }
                }
            }
        } else {
            message.setRecipient(RecipientType.TO, new InternetAddress(EmailUtils.toEmailAccount, EmailUtils.toEmailShow, EMAIL_CHARSET));
        }
        // 抄送列表
        if (ccMap != null) {
            if (ccMap.size() > 0) {
                Set<String> emailShows = ccMap.keySet();
                String[] emailShowsStr = new String[emailShows.size()];
                emailShows.toArray(emailShowsStr);
                for (int i = 0; i < emailShowsStr.length; i++) {
                    if (i == 0) {
                        //RecipientType.TO:普通发送
                        //RecipientType.CC:抄送
                        //RecipientType.BCC:密送
                        message.setRecipient(RecipientType.CC, new InternetAddress(ccMap.get(emailShowsStr[i]).toString(), emailShowsStr[i], EMAIL_CHARSET));
                    } else {
                        message.addRecipient(RecipientType.CC, new InternetAddress(ccMap.get(emailShowsStr[i]).toString(), emailShowsStr[i], EMAIL_CHARSET));
                    }
                }
            }
        } else {
            message.setRecipient(RecipientType.CC, new InternetAddress(EmailUtils.toEmailAccount, EmailUtils.toEmailShow, EMAIL_CHARSET));
        }
        // 4. Subject: 邮件主题
        message.setSubject(EmailUtils.emailSubject, EmailUtils.EMAIL_CHARSET);
        // 5. Content: 邮件正文(可以使用html标签)
        //简单内容
        //message.setContent(EmailUtils.emailContent, EmailUtils.CONTENT_CHARSET);
        //复杂内容(带有图片、文本、附件)
        message.setContent(crateMimeMultipartContent());
        // 6. 设置发件时间
        message.setSentDate(EmailUtils.emailSendDate);
        // 7. 保存设置
        message.saveChanges();
        return message;
    }

    /**
     * 创建复杂邮件内容正文
     *
     * @return
     */
    private static MimeMultipart crateMimeMultipartContent() {
        MimeMultipart mimeMultipart = null;
        try {
            //创建文本“节点”
            MimeBodyPart text = new MimeBodyPart();
            //这里添加图片的方式是将整个图片包含到邮件内容中, 实际上也可以以 http 链接的形式添加网络图片
            text.setContent(EmailUtils.emailContent, CONTENT_CHARSET);

            //将 文本 和 图片 “节点”合成一个混合“节点”
            MimeMultipart mm_text_image = new MimeMultipart();
            //放入文本
            mm_text_image.addBodyPart(text);
            //创建并放入图片
            if (imageFilesMap != null && imageFilesMap.size() > 0) {
                Set<String> contentIDs = imageFilesMap.keySet();
                String[] contentIDsArr = new String[contentIDs.size()];
                contentIDs.toArray(contentIDsArr);
                for (int i = 0; i < contentIDsArr.length; i++) {
                    // 创建图片“节点”
                    MimeBodyPart image = new MimeBodyPart();
                    // 读取本地文件
                    DataHandler imageHander = new DataHandler(new FileDataSource((File) imageFilesMap.get(contentIDsArr[i])));
                    // 将图片数据添加到“节点”
                    image.setDataHandler(imageHander);
                    // 为“节点”设置一个唯一编号(在文本“节点”将引用该ID)
                    image.setContentID(contentIDsArr[i]);
                    //放入图片(可以放入多张)
                    mm_text_image.addBodyPart(image);
                }
            }
            // 关联关系 setSubType:设置子类型。该方法只能在由客户端创建的新的MimeMultipart对象上调用。这种多部分对象的默认子类型为“mixed”。
            mm_text_image.setSubType("related");

            //将 文本+图片 的混合“节点”封装成一个普通“节点”
            MimeBodyPart text_image = new MimeBodyPart();
            text_image.setContent(mm_text_image);

            //合成一个大的混合“节点”
            mimeMultipart = new MimeMultipart();
            //放入 文本+图片 节点
            mimeMultipart.addBodyPart(text_image);
            //放入附件
            if (attachContentsList != null && attachContentsList.size() > 0) {
                for (File file : attachContentsList) {
                    //创建附件“节点”
                    MimeBodyPart attachContent = new MimeBodyPart();
                    // 读取本地文件
                    DataHandler attachContentHander = new DataHandler(new FileDataSource(file));
                    // 将附件数据添加到“节点”
                    attachContent.setDataHandler(attachContentHander);
                    // 设置附件的文件名(需要编码)
                    attachContent.setFileName(MimeUtility.encodeText(attachContentHander.getName()));
                    //放入附件节点(如果有多个附件,可以创建多个多次添加)
                    mimeMultipart.addBodyPart(attachContent);
                }
            }
            //混合关系
            mimeMultipart.setSubType("mixed");

        } catch (Exception e) {
            e.printStackTrace();
        }
        return mimeMultipart;
    }

    @Value("${mail.fromEmailAccount}")
    public void setFromEmailAccount(String fromEmailAccount) {
        EmailUtils.fromEmailAccount = fromEmailAccount;
    }

    @Value("${mail.fromEmailPassword}")
    public void setFromEmailPassword(String fromEmailPassword) {
        EmailUtils.fromEmailPassword = fromEmailPassword;
    }

    @Value("${mail.formEmailSMTPHOST}")
    public void setFormEmailSMTPHOST(String formEmailSMTPHOST) {
        EmailUtils.formEmailSMTPHOST = formEmailSMTPHOST;
    }
}

yml文件配置

在这里插入图片描述

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java邮件发送工具JavaMail API。可以使用JavaMail API来发送文本邮件、HTML邮件、带附件的邮件等。 在Java中,可以使用MimeMessage类和MimeMessageHelper类来创建并发送邮件。首先,需要添加依赖项javax.mail到项目的pom.xml文件中: ``` <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4</version> </dependency> ``` 然后,可以使用以下代码来创建和发送邮件: ```java import javax.mail.*; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessageHelper; public class EmailSender { public static void sendEmail(String to, String subject, String content, String from) { // 创建Session对象 Session session = Session.getDefaultInstance(new Properties()); try { // 创建MimeMessage对象 MimeMessage message = new MimeMessage(session); // 设置发件人 message.setFrom(new InternetAddress(from)); // 设置收件人 message.addRecipient(Message.RecipientType.TO, new InternetAddress(to)); // 设置主题 message.setSubject(subject); // 设置内容 message.setContent(content, "text/html"); // 发送邮件 Transport.send(message); System.out.println("邮件发送成功"); } catch (MessagingException e) { System.err.println("邮件发送失败"); } } } ``` 以上是一个简单的Java邮件发送工具类的示例。使用该工具类可以发送包含HTML代码的邮件。你可以调用`sendEmail`方法来发送邮件,其中`to`参数是收件人的邮箱地址,`subject`参数是邮件的主题,`content`参数是邮件的内容,`from`参数是发件人的邮箱地址。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值