/* * The following code will send a verification code to a player after they set their email with 'setemail'. * After verifying their email the MUD can then be used to send other emails (password recovery, immortal note, etc). * * This was written for AckFUSS 4.4.1 but should port easily to any Diku-based game. Substitute char * fields for string * fields and adjust as needed if you are compiling with gcc instead of g++. * * STEP 1: * Add the defines for do_verify_email() and do_set_email() to your command table/headers like any other command. * * STEP 2: * Add the following struct to your primary .h file * struct email_data * { * bool verified; * string address; * string confirmation_code; * }; * Then declare the following typedef with your other typedefs * typedef struct email_data EMAIL_DATA; * Finally, add it to your char_data or pc_data struct where applicable. * NOTE: Be sure to make proper new/delete memory calls in your character create/delete routines. * EMAIL_DATA *email; * * STEP 3: * Add fields in your save/load player routines to save all the values of your new email_data struct. * * STEP 4: * Adjust things to fit your game, such as mudnamecolor, the EMAIL_FILE logging, and monitor_chan notifications. * * STEP 5: * Ensure your system is setup for command line email. You can test via your shell with the following: * echo "This is the body text." | mail -s "Testing CLI Email" "your@email.com" * * STEP 6: * Fix anything broken with your server's email daemon if you don't receive your email from step 4 :). * * Feel free to modify this code to suit your needs, and if you have a great improvement I wouldn't mind if you * shared it with me either, if you're so inclined :D. All I ask is to give me credit for the code if you do * choose to use it. * * --Kline (Matt Goff) */ DO_FUN(do_verify_email) { if ( IS_NPC( ch ) ) return; if ( ch->pcdata->email->address.empty() ) { ch->send( "You need to provide an email address first with setemail <address>.\r\n" ); return; } if ( ch->pcdata->email->verified ) { ch->send( "You have already verified your email. If you wish to update your email, please use setemail <address>.\r\n" ); return; } if ( argument[0] == '\0' ) { ch->send( "To verify your email address you must everify <code> using the code you received.\r\n" ); return; } if ( !str_cmp( argument, ch->pcdata->email->confirmation_code ) ) { ch->send( "Thank you for verifying your email address.\r\n"); ch->pcdata->email->confirmation_code.clear(); ch->pcdata->email->verified = true; snprintf( log_buf, MSL, "%s (%s) has verified their email address.", ch->get_name(), ch->pcdata->email->address.c_str() ); monitor_chan( log_buf, MONITOR_EMAIL ); return; } else { ch->send( "Invalid code. If you did not receive a validation code please reset your email using the setemail command.\r\n" ); return; } return; } DO_FUN(do_set_email) { char body[MSL], subject[MSL]; if ( IS_NPC( ch ) ) return; if ( argument[0] == '\0' ) { ch->send( "You didn't provide an email address. Syntax is setemail <email>.\r\n" ); return; } ch->pcdata->email->address = argument; ch->pcdata->email->confirmation_code.clear(); ch->pcdata->email->confirmation_code = gen_rand_string(8); ch->pcdata->email->verified = false; ch->send( "An email has been sent to %s with a confirmation code. Please verify your address by typing everify <code> once your have received the email. If you do not receive an email, set your email again and a new code will be sent.\r\n", argument ); snprintf( subject, MSL, "%s Email Confirmation Code", mudnamenocolor ); snprintf( body, MSL, "<html>This email was used by a player of %s. If this was not you, please disregard it.<br><br>Confirmation code: <b>%s</b></html>", mudnamenocolor, ch->pcdata->email->confirmation_code.c_str() ); send_email( argument, subject, body, false, ch); return; } bool send_email( const char *address, const char *subject, const char *body, bool validate, CHAR_DATA *ch ) { char mailbuf[MSL]; FILE *fp; if( IS_NPC(ch) ) /* Safety check for later --Kline */ ch = NULL; if ( validate && ch != NULL && !ch->pcdata->email->verified ) { snprintf( log_buf, MSL, "Unable to send email to %s (%s); email not verified.", ch->get_name(), ch->pcdata->email->address.c_str() ); monitor_chan( log_buf, MONITOR_EMAIL ); return false; } snprintf( mailbuf, MSL, "echo \"%s\" | mail -a \"Content-type: text/html;\" -s \"%s\" \"%s\"", body, subject, ch == NULL ? address : ch->pcdata->email->address.c_str() ); /* * system() is if() encapsulated to suppress a warning. system() returns different results on different distros, * so there is no reliable return value to check against. --Kline */ if ( system( mailbuf ) ) {} if( ch == NULL ) snprintf( log_buf, MSL, "An email was sent to (%s) with subject (%s).", address, subject ); else snprintf( log_buf, MSL, "An email was sent to %s (%s) with subject (%s).", ch->get_name(), ch->pcdata->email->address.c_str(), subject ); monitor_chan( log_buf, MONITOR_EMAIL ); if ( ( fp = file_open( EMAIL_FILE, "a" ) ) != NULL ) { fprintf( fp, "%s :: %s\n", current_time_str(), mailbuf ); file_close( fp ); } return true; } const char *gen_rand_string( int length ) { int i, r; char tmp[2]; static char output[MSL]; const char valid[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; srand ( current_time ); for ( i = 0; i < length; i++ ) { r = rand() % strlen(valid); snprintf( tmp, 2, "%c", valid[r] ); if ( i == 0 ) snprintf ( output, length+1, "%s", tmp ); else strncat ( output, tmp, length+1 ); } return output; } const char *current_time_str( void ) { char *strtime; static char output[MSL]; strtime = ctime( ¤t_time ); strtime[strlen( strtime ) - 1] = '\0'; snprintf( output, MSL, "%s", strtime ); return output; }