diff --git a/app/views/teachers/TeachersContactModal.coffee b/app/views/teachers/TeachersContactModal.coffee index 57ee0bc58..ec19bd824 100644 --- a/app/views/teachers/TeachersContactModal.coffee +++ b/app/views/teachers/TeachersContactModal.coffee @@ -55,7 +55,7 @@ module.exports = class TeachersContactModal extends ModalView return unless _.isEmpty(formErrors) @state.set('sendingState', 'sending') - data = _.extend({ country: me.get('country'), recipientID: 'schools@codecombat.com' }, formValues) + data = _.extend({ country: me.get('country'), recipientID: 'schools@codecombat.com', enrollmentsNeeded: @enrollmentsNeeded }, formValues) contact.send({ data context: @ diff --git a/server/lib/closeIO.coffee b/server/lib/closeIO.coffee index be254091f..5e15b92a5 100644 --- a/server/lib/closeIO.coffee +++ b/server/lib/closeIO.coffee @@ -57,7 +57,7 @@ module.exports = return done(error) if error leads = JSON.parse(body) return done("Unexpected leads format: " + body) unless leads.data? - return done(null, config.mail.supportSchools) unless leads.data?.length > 0 + return done("No existing Close.IO lead found for #{email}") unless leads.data?.length > 0 lead = leads.data[0] uri = "https://#{apiKey}:X@app.close.io/api/v1/activity/?lead_id=#{lead.id}" request.get uri, (error, response, body) => @@ -65,8 +65,33 @@ module.exports = activities = JSON.parse(body) return done("Unexpected activities format: " + body) unless activities.data? for activity in activities.data when activity._type is 'Email' - return done(null, activity.sender) if /@codecombat\.com/ig.test(activity.sender) - return done(null, config.mail.supportSchools) + if /@codecombat\.com/ig.test(activity.sender) and not activity.sender?.indexOf(config.mail.username) >= 0 + return done(null, activity.sender, lead.id) + return done(null, config.mail.supportSchools, lead.id) catch error log.error("closeIO.getSalesContactEmail Error for #{email}: #{JSON.stringify(error)}") - return done(error, config.mail.supportSchools) + return done(error) + + sendMail: (fromAddress, subject, content, done) -> + # log.info("DEBUG: closeIO.sendMail #{fromAddress} #{subject} #{content}") + @getSalesContactEmail fromAddress, (err, salesContactEmail, leadID) -> + return done("Error getting sales contact for #{fromAddress}: #{err}") if err + matches = salesContactEmail.match(/^[a-zA-Z_]+ <(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3})>$|(\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3})/i) + salesContactEmail = matches?[1] ? matches?[2] ? config.mail.supportSchools + postData = + to: [salesContactEmail] + sender: config.mail.username + subject: subject + body_text: content + lead_id: leadID + status: 'outbox' + options = + uri: "https://#{apiKey}:X@app.close.io/api/v1/activity/email/" + body: JSON.stringify(postData) + request.post options, (error, response, body) => + return done(error) if error + result = JSON.parse(body); + if result.errors or result['field-errors'] + errorMessage = "Close.io Send email POST error for #{fromAddress} #{JSON.stringify(result.errors)} #{JSON.stringify(result['field-errors'])}"; + return done(errorMessage) + return done() diff --git a/server/routes/contact.coffee b/server/routes/contact.coffee index cce6e96e3..651639bcb 100644 --- a/server/routes/contact.coffee +++ b/server/routes/contact.coffee @@ -11,21 +11,27 @@ module.exports.setup = (app) -> app.post '/contact', (req, res) -> return res.end() unless req.user # log.info "Sending mail from #{req.body.email} saying #{req.body.message}" - createMailContext req, (context) -> - sendwithus.api.send context, (err, result) -> - if err - log.error "Error sending contact form email: #{err.message or err}" + fromAddress = req.body.sender or req.body.email or req.user.get('email') + createMailContent req, fromAddress, (subject, content) -> + if req.body.recipientID is 'schools@codecombat.com' or req.user.isTeacher() + req.user.update({$set: { enrollmentRequestSent: true }}).exec(_.noop) if req.body.recipientID is 'schools@codecombat.com' + closeIO.sendMail fromAddress, subject, content, (err) -> + log.error "Error sending contact form email via Close.io: #{err.message or err}" if err + else + createSendWithUsContext req, fromAddress, subject, content, (context) -> + sendwithus.api.send context, (err, result) -> + log.error "Error sending contact form email via sendwithus: #{err.message or err}" if err return res.end() -createMailContext = (req, done) -> - sender = req.body.sender or req.body.email +createMailContent = (req, fromAddress, done) -> + country = req.body.country + enrollmentsNeeded = req.body.enrollmentsNeeded message = req.body.message user = req.user - recipientID = req.body.recipientID - subject = req.body.subject - country = req.body.country - sentFromLevel = levelID: req.body.levelID, courseID: req.body.courseID, courseInstanceID: req.body.courseInstanceID - + subject = switch + when enrollmentsNeeded then "#{enrollmentsNeeded} Licenses needed for #{fromAddress}" + when req.body.subject then req.body.subject + else "Contact Us Form: #{fromAddress}" level = if user?.get('points') > 0 then Math.floor(5 * Math.log((1 / 100) * (user.get('points') + 100))) + 1 else 0 premium = user?.isPremium() teacher = user?.isTeacher() @@ -34,15 +40,25 @@ createMailContext = (req, done) -> -- http://codecombat.com/user/#{user.get('slug') or user.get('_id')} - #{user.get('name') or 'Anonymous'} - Level #{level}#{if teacher then ' - Teacher' else ''}#{if premium then ' - Subscriber' else ''}#{if country then ' - ' + country else ''} + #{fromAddress} - #{user.get('name') or 'Anonymous'} - Level #{level}#{if teacher then ' - Teacher' else ''}#{if premium then ' - Subscriber' else ''}#{if country then ' - ' + country else ''} """ if req.body.browser content += "\n#{req.body.browser} - #{req.body.screenSize}" + done(subject, content) + +createSendWithUsContext = (req, fromAddress, subject, content, done) -> + user = req.user + recipientID = req.body.recipientID + sentFromLevel = levelID: req.body.levelID, courseID: req.body.courseID, courseInstanceID: req.body.courseInstanceID + premium = user?.isPremium() + teacher = user?.isTeacher() + + if recipientID is 'schools@codecombat.com' or teacher + return done("Tried to send a teacher contact us email via sendwithus #{fromAddress} #{subject}") toAddress = switch when premium then config.mail.supportPremium else config.mail.supportPrimary - fromAddress = sender or user.get('email') context = email_id: sendwithus.templates.plain_text_email @@ -53,30 +69,24 @@ createMailContext = (req, done) -> reply_to: fromAddress name: user.get('name') email_data: - subject: "[CodeCombat] #{subject ? ('Feedback - ' + fromAddress)}" + subject: subject content: content contentHTML: content.replace /\n/g, '\n<br>' - if recipientID is 'schools@codecombat.com' or teacher - req.user.update({$set: { enrollmentRequestSent: true }}).exec(_.noop) if recipientID is 'schools@codecombat.com' - closeIO.getSalesContactEmail fromAddress, (err, salesContactEmail) -> - console.error "Error getting sales contact for #{sender}: #{err}" if err - context.recipient.address = salesContactEmail ? config.mail.supportSchools - done context - else if recipientID and (user.isAdmin() or ('employer' in (user.get('permissions') ? []))) + if recipientID and (user.isAdmin() or ('employer' in (user.get('permissions') ? []))) User.findById(recipientID, 'email').exec (err, document) -> if err log.error "Error looking up recipient to email from #{recipientID}: #{err}" if err else - context.recipient.bcc = [context.recipient.address, sender] + context.recipient.bcc = [context.recipient.address, fromAddress] context.recipient.address = document.get('email') - context.email_data.content = message + context.email_data.content = content done context else async.waterfall [ fetchRecentSessions.bind undefined, user, context, sentFromLevel # Can add other data-grabbing stuff here if we want. ], (err, results) -> - console.error "Error getting contact message context for #{sender}: #{err}" if err + console.error "Error getting contact message context for #{fromAddress}: #{err}" if err if req.body.screenshotURL context.email_data.contentHTML += "\n<br><img src='#{req.body.screenshotURL}' />" done context