func checkNumber(config *periwinkle.Cfg, tx *periwinkle.Tx, number backend.TwilioNumber) { url := "https://api.twilio.com/2010-04-01/Accounts/" + config.TwilioAccountID + "/Messages.json?To=" + number.Number if lastPoll != timeZero { url += "&DateSent>=" + strings.Split(lastPoll.UTC().String(), " ")[0] } req, _ := http.NewRequest("GET", url, nil) req.SetBasicAuth(config.TwilioAccountID, config.TwilioAuthToken) resp, uerr := (&http.Client{}).Do(req) if uerr != nil { periwinkle.LogErr(locale.UntranslatedError(uerr)) } defer resp.Body.Close() body, uerr := ioutil.ReadAll(resp.Body) if uerr != nil { periwinkle.LogErr(locale.UntranslatedError(uerr)) } // converts JSON messages var page twilio.Paging json.Unmarshal([]byte(body), &page) for _, message := range page.Messages { timeSend, uerr := time.Parse(time.RFC1123Z, message.DateSent) if uerr != nil { periwinkle.LogErr(locale.UntranslatedError(uerr)) continue } if timeSend.Unix() < lastPoll.Unix() { periwinkle.Logf("message %q older than our last poll; ignoring", message.Sid) continue } user := backend.GetUserByAddress(tx, "sms", message.From) if user == nil { periwinkle.Logf("could not figure out which user has number %q", message.From) continue } group := backend.GetGroupByUserAndTwilioNumber(tx, user.ID, message.To) if group == nil { periwinkle.Logf("could not figure out which group this is meant for: user: %q, number: %q", user.ID, message.To) continue } periwinkle.Logf("received message for group %q", group.ID) MessageBuilder{ Maildir: config.Mailstore, Headers: map[string]string{ "To": group.ID + "@" + config.GroupDomain, "From": backend.UserAddress{Medium: "sms", Address: message.From}.AsEmailAddress(), "Subject": user.ID + ": " + message.Body, }, Body: "", }.Done() } }
func HandleSMS(r io.Reader, name string, db *periwinkle.Tx, cfg *periwinkle.Cfg) postfixpipe.ExitStatus { message, uerr := mail.ReadMessage(r) if uerr != nil { periwinkle.LogErr(locale.UntranslatedError(uerr)) return postfixpipe.EX_NOINPUT } group := message.Header.Get("From") user := backend.GetUserByAddress(db, "sms", name) smsFrom := backend.GetTwilioNumberByUserAndGroup(db, user.ID, strings.Split(group, "@")[0]) if smsFrom == "" { twilio_num := twilio.GetUnusedTwilioNumbersByUser(cfg, db, user.ID) if twilio_num == nil { new_num, err := twilio.NewPhoneNum(cfg) if err != nil { periwinkle.LogErr(err) return postfixpipe.EX_UNAVAILABLE } backend.AssignTwilioNumber(db, user.ID, strings.Split(group, "@")[0], new_num) smsFrom = new_num } else { backend.AssignTwilioNumber(db, user.ID, strings.Split(group, "@")[0], twilio_num[0]) smsFrom = twilio_num[0] } } smsBody := message.Header.Get("Subject") //smsBody, err := ioutil.ReadAll(message.Body) //if err != nil { // return "", err //} messagesURL := "https://api.twilio.com/2010-04-01/Accounts/" + cfg.TwilioAccountID + "/Messages.json" v := url.Values{} v.Set("From", smsFrom) v.Set("To", name) v.Set("Body", string(smsBody)) v.Set("StatusCallback", cfg.WebRoot+"/callbacks/twilio-sms") //host,_ := os.Hostname() //v.Set("StatusCallback", "http://" + host + ":8080/callbacks/twilio-sms") client := &http.Client{} req, uerr := http.NewRequest("POST", messagesURL, bytes.NewBuffer([]byte(v.Encode()))) if uerr != nil { periwinkle.LogErr(locale.UntranslatedError(uerr)) return postfixpipe.EX_UNAVAILABLE } req.SetBasicAuth(cfg.TwilioAccountID, cfg.TwilioAuthToken) req.Header.Add("Accept", "application/json") req.Header.Add("Content-Type", "application/x-www-form-urlencoded") resp, uerr := client.Do(req) defer resp.Body.Close() if uerr != nil { periwinkle.LogErr(locale.UntranslatedError(uerr)) return postfixpipe.EX_UNAVAILABLE } if resp.StatusCode != 200 && resp.StatusCode != 201 { return postfixpipe.EX_UNAVAILABLE } body, uerr := ioutil.ReadAll(resp.Body) if uerr != nil { periwinkle.LogErr(locale.UntranslatedError(uerr)) return postfixpipe.EX_UNAVAILABLE } return postfixpipe.EX_OK tmessage := twilio.Message{} json.Unmarshal([]byte(body), &tmessage) _, err := TwilioSMSWaitForCallback(cfg, tmessage.Sid) if err != nil { periwinkle.LogErr(err) return postfixpipe.EX_UNAVAILABLE } return postfixpipe.EX_OK }