zoukankan      html  css  js  c++  java
  • javaMail发邮件,激活用户账号

    用javamail实现注册用户验证邮箱功能。用户注册后随机生成一个uuid作为用户的标识,传递给用户然后作为路径参数。发送html的内容到用户注册的邮箱里,若用户点击后去往的页面提交username和password比对成功,则用户验证成功。

    下面介绍代码。我用的是shiro作为安全框架。实际上我只用来做权限控制,这里不介绍shiro。springmvc作前端控制器,hibernate作数据库操作(为什么不用mybatis?我也很后悔没有用mybatis)用户注册代码

        @RequestMapping("base/register")
        public String register(User u, Model model) {
            if (u != null && StringUtils.isNoneBlank(u.getPassword()) && StringUtils.isNotBlank(u.getUsername())) {
                boolean nameExi = userService.checkUserName(u.getUsername());
                if (!nameExi) {
                    // 为用户创建‘用户’角色
                    u.setPassword(Md5Utils.toMd5(u.getPassword(), u.getUsername(), 2));
                    Role role = roleService.getRoleByRoleName("游客");
                    u.setRole(role);
                    u.setRegisterDate(new Date());
                    u.setActivecode(UUID.randomUUID().toString().replace("-", ""));
                    userService.register(u);
                    String ip="";
                    errorInfo = "请在邮箱中激活您的账户";
                    try {
                        InetAddress addr=InetAddress.getLocalHost();
                        ip =addr.getHostAddress();
                    } catch (UnknownHostException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    User registerU = userService.checkRealmUserName(u.getUsername());
                    String subject="发给-"+registerU.getUsername();
                    String email=registerU.getEmail();
                    String msg="<h2>hi"+registerU.getUsername()+"</h2><hr><h4>thanks for reading this email and  click this link to active your account<a href='http://"+ip+":8080/myone-web/base/activeCount?activecode="+registerU.getActivecode()+"'>点击这里激活您的账户</a></h4>";
                    MailSender mailSender=new MailSender();
                    mailSender.sendActiveMail(msg, subject, email, javaMailSender);
                    model.addAttribute("errorInfo", errorInfo);
                    return "user_login"; // 用户注册成功
                }
                // 用户注册失败
                errorInfo = "注册失败  用户名已存在  或注册信息有误";
                model.addAttribute("errorInfo", errorInfo);
    
            }
            return "error";
        }

    如果又看不懂的代码可以不看主要看传递邮箱的参数即可,这里还有一个注入了一个JavaMailSender类。新建发送邮件的项目:

    创建maven项目加入依赖

    <dependency>
                <groupId>javax.mail</groupId>
                <artifactId>mail</artifactId>
                <version>1.4.7</version>
            </dependency>

    我用了spring这里也给出

    <!-- spring -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-orm</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>4.3.4.RELEASE</version>
            </dependency>

    这些依赖只会多不会少 注意我这里没有version参数 因为我在之前做了锁定

    <properties>
            <spring.version>4.2.4.RELEASE</spring.version>
            <hibernate.version>5.0.7.Final</hibernate.version>
            <jackson.version>2.7.3</jackson.version>
        </properties>

    javamail需要的包都在第一个依赖里

    spring的applicationContext.xml部分配置文件

        <!-- 邮件配置 -->
        <context:property-placeholder location="classpath:mail.properties" />
        
        <!-- 邮件接口 -->
        <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
            <property name="host" value="${mail.smtp.host}"></property>
            <property name="username" value="${mail.smtp.username}"></property>
            <property name="password" value="${mail.smtp.password}"></property>
            <property name="defaultEncoding" value="${mail.smtp.defaultEncoding}"></property>
            <property name="javaMailProperties">
                <props>
                    <prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
                    <prop key="mail.smtp.timeout">${mail.smtp.timeout}</prop>
                </props>
            </property>
        </bean>

    mail.properties配置文件

    mail.smtp.host=smtp.163.com
    
    mail.smtp.username=。。。。。@163.com
    
    mail.smtp.password=。。。
    
    mail.smtp.defaultEncoding=utf-8
    
    mail.smtp.auth=true
    
    mail.smtp.timeout=20000

    放到resouce目录下或者选中文件夹build classpath

    下面是我写的已sendMail实现,其实就两个方法,一个单独发送,一个发送多个联系人

    package com.dabai.utils;
    
    import java.util.Properties;
    
    import javax.mail.internet.InternetAddress;
    import javax.mail.internet.MimeMessage;
    
    import org.springframework.mail.javamail.JavaMailSender;
    import org.springframework.mail.javamail.MimeMessageHelper;
    
    /**  
    * @author dabai: 
    
    * 类说明  发送邮件工具类
    */
    public class MailSender {
        //用户激活邮件
        public String sendActiveMail(String msg,String subject,String userEmail,JavaMailSender javaMailSender){
            //创建邮件对象
            MimeMessage mMessage =javaMailSender.createMimeMessage();
            MimeMessageHelper mMessageHelper;
            Properties prop=new Properties();
            //获取发送邮件参数
            try {
                prop.load(this.getClass().getResourceAsStream("/mail.properties"));
                String from =prop.get("mail.smtp.username")+"";
                mMessageHelper=new MimeMessageHelper(mMessage,true,"UTF-8");
                //发送邮箱
                mMessageHelper.setFrom(from);
                //收件人
                mMessageHelper.setTo(userEmail);
                //邮件标题 主题
                mMessageHelper.setSubject(subject);
                //设置邮件文本内容为html
                mMessageHelper.setText(msg,true);
                 
                //发送
                javaMailSender.send(mMessage);
            } catch (Exception e) {
                e.printStackTrace();
                return " email send fail";
            }
            
            return "email send success";
        }
        //生日祝福邮件
        public String sendWish(String msg,String subject,InternetAddress[] emails,JavaMailSender javaMailSender){
            //创建邮件对象
                    MimeMessage mMessage =javaMailSender.createMimeMessage();
                    MimeMessageHelper mMessageHelper;
                    Properties prop=new Properties();
                    //获取发送邮件参数
            try {
                prop.load(this.getClass().getResourceAsStream("/mail.properties"));
                String from =prop.get("mail.smtp.username")+"";
                mMessageHelper=new MimeMessageHelper(mMessage,true,"UTF-8");
                //发送邮箱
                mMessageHelper.setFrom(from);
                mMessageHelper.setSubject(subject);
                mMessageHelper.setText(msg,true);
                mMessageHelper.setTo(emails);
                 
                javaMailSender.send(mMessage);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return "email send finished";
        }
    
    }

    两个方法上面是用户注册是发送验证邮箱链接的,下面的方法是根据用户birthday给指定人发送邮件祝福,用quartz实现定时,此处不介绍

      下面是用户注册逻辑 使用上面的第一个方法发送邮件

    这里介绍下传递的参数  第一个方法的:

    这一块:没有部署到远程主机上可以不用,url的路径写死即可,如果有域名的话写域名也ok对应这发送的信息  msg

    String msg="<h2>hi"+registerU.getUsername()+"</h2><hr><h4>thanks for reading this email and  click this link to active your account<a href='http://"+ip+":8080/myone-web/base/activeCount?activecode="+registerU.getActivecode()+"'>点击这里激活您的账户</a></h4>";

    html没问题吧不做解释。subject  :string类型即可 发送邮件的主题

    email 接收邮件的邮件地址 单个发可以写成string类型的  多个接收方要换成InternetAddress【】类型,转换也比较烦人。

    MailSender  :就是我写的那个 方法类

    javaMailSender这就是前面在spring中注入的那个javamailImpl 。前面给出了配置 在你需要用到的地方@Autowired即可。

    如果有用网易163的朋友可能会报

    554 DT:SPM

    这样子的错误  通常是因为邮件的subject写的比较繁杂,就是花里胡哨的

    其他的错误代码可参照

    http://help.163.com/09/1224/17/5RAJ4LMH00753VB8.html

    关于 MailSender工具类  大部分我在注释上给出了 这里说一下  下面setText后面跟的参数的意思  设置为false代表你只在msg中设置字符串,如果你想在msg中写html格式就要改成true  如设置为false 邮件显示msg内容为:    <h1>dabai</h1>

    设置为true邮件msg内容就是

    dabai

    mMessageHelper.setText(msg,true);

     

     关于发送给多个接收者:

    就是MailSender类的第二个方法  同样这里给出使用方法

    package com.dabai.jobs;
    
    import java.util.ArrayList;
    import java.util.Calendar;
    import java.util.Date;
    import java.util.List;
    
    import javax.mail.internet.AddressException;
    import javax.mail.internet.InternetAddress;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.mail.javamail.JavaMailSender;
    
    import com.dabai.service.UserService;
    import com.dabai.utils.MailSender;
    
    /**  
    * @author dabai: 
    
    * 类说明  查找当日生日的用户 发送生日祝福邮件类
    */
    public class SendBirthdayWish {
        @Autowired
        private UserService userService;
        @Autowired
        private JavaMailSender javaMailSender;
        public void sendWish() throws AddressException{
            Calendar date=Calendar.getInstance();
            int month=date.get(Calendar.MONTH)+1;
            int day = date.get(Calendar.DAY_OF_MONTH);
            
            List<String>emails=userService.findBirthdayEmails(month,day);//根据当日的月份和天数从数据库中查询用户邮箱   因为我这里注册需要邮箱所以不存在为空的情况 这里不需判断 但我还是加了上去。。。  实际使用请斟酌一二
            if(emails!=null&&emails.size()>0){              //这里的一串代码可能看的有些迷糊  但是的确不好省掉  首先注意下我查出来的是List<String>的集合  然后我又把它换成String[]数组形式存储 然后再用List接收经过InternetAddress转换后的emal地址
                                           //最后用InternetAddress[]数组接收
    String[]array
    =new String[emails.size()]; List list=new ArrayList(); InternetAddress[]address=null; for (int i=0;i<emails.size();i++) { array[i]=emails.get(i); } for(int i=0;i<array.length;i++){ list.add(new InternetAddress(array[i])); } address=(InternetAddress[]) list.toArray(new InternetAddress[list.size()]); String msg="<h2> hi Dear</h2><br><b><pre>today is"+month+""+day+"日 and it's your birthday! happy birthday to you </pre></b>"; String subject="祝你生日快乐"; MailSender mailsender=new MailSender(); mailsender.sendWish(msg, subject, address, javaMailSender);      //msg就是发送的信息 内容 subject 邮件主题 string类型即可 address 如果是多个接收者必须用InternetAddress[] }else{ System.out.println("today nobody birthday"+new Date().toString()); } } }

    下面是我踩得一些坑

    DEBUG [schedulerFactoryBean_Worker-1] - trace com.mchange.v2.resourcepool.BasicResourcePool@7af9a2cc [managed: 3, unused: 1, excluded: 0] (e.g. com.mchange.v2.c3p0.impl.NewPooledConnection@231bf06e)
    ERROR [schedulerFactoryBean_Worker-1] - Job DEFAULT.sendWishJob threw an unhandled Exception: 
    org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'sendWish' on target class [class com.dabai.jobs.SendBirthdayWish] failed; nested exception is java.lang.ArrayStoreException
        at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:266)
        at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
    Caused by: java.lang.ArrayStoreException
        at java.lang.System.arraycopy(Native Method)
        at java.util.ArrayList.toArray(ArrayList.java:390)
        at com.dabai.jobs.SendBirthdayWish.sendWish(SendBirthdayWish.java:32)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:269)
        at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:257)
        ... 3 more
    ERROR [schedulerFactoryBean_Worker-1] - Job (DEFAULT.sendWishJob threw an exception.
    org.quartz.SchedulerException: Job threw an unhandled exception. [See nested exception: org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'sendWish' on target class [class com.dabai.jobs.SendBirthdayWish] failed; nested exception is java.lang.ArrayStoreException]
        at org.quartz.core.JobRunShell.run(JobRunShell.java:213)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
    Caused by: org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'sendWish' on target class [class com.dabai.jobs.SendBirthdayWish] failed; nested exception is java.lang.ArrayStoreException
        at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:266)
        at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
        ... 1 more
    Caused by: java.lang.ArrayStoreException
        at java.lang.System.arraycopy(Native Method)
        at java.util.ArrayList.toArray(ArrayList.java:390)
        at com.dabai.jobs.SendBirthdayWish.sendWish(SendBirthdayWish.java:32)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:269)
        at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:257)
        ... 3 more
        
        

    如果地址不经转换就会报上面那个错误

    还一个就是

     java.lang.ArrayIndexOutOfBoundsException: 0

    在最初的转换中我用String[]array=new String[]{};

    接收  再逐个放入然后逐个放入的代码报了上面那个越界错误需要改成:犯这种错实在不应当,

    String[]array=new String[emails.size()];

     

  • 相关阅读:
    两个链表的第一个公共节点(Python and C++解法)
    第一个只出现一次的字符(Python and C++解法)
    丑数(Python and C++解法)
    最长不含重复字符的子字符串(Python and C++解法)
    礼物的最大值(Python and C++解法)
    把数字翻译成字符串(Python and C++解法)
    连续子数组的最大和(Python and C++解法)
    最小的k个数(Python and C++解法)
    数组中出现次数超过一半的数字(Python and C++解法)
    字符串的排列(Python and C++解法)
  • 原文地址:https://www.cnblogs.com/notably/p/10590418.html
Copyright © 2011-2022 走看看