@@ -253,12 +253,6 @@ func createMessageDraft(ctx context.Context, w io.Writer, draft draftFormRequest
253253}
254254
255255func createReplyDraft (ctx context.Context , w io.Writer , threadID int64 , draft draftFormRequest ) error {
256- topicResp , err := sdk .GetHTML (ctx , fmt .Sprintf ("/topics/%d" , threadID ))
257- if err != nil {
258- return convertSDKError (err )
259- }
260- addressed := htmlutil .ParseTopicAddressed (string (topicResp .Data ))
261-
262256 entriesResp , err := sdk .GetHTML (ctx , fmt .Sprintf ("/topics/%d/entries" , threadID ))
263257 if err != nil {
264258 return convertSDKError (err )
@@ -268,14 +262,7 @@ func createReplyDraft(ctx context.Context, w io.Writer, threadID int64, draft dr
268262 return output .ErrNotFound ("entries for thread" , fmt .Sprintf ("%d" , threadID ))
269263 }
270264
271- latestEntryID := entries [len (entries )- 1 ].ID
272- if len (draft .To ) == 0 && len (draft .CC ) == 0 && len (draft .BCC ) == 0 {
273- draft .To = addressed .To
274- draft .CC = addressed .CC
275- draft .BCC = addressed .BCC
276- }
277-
278- return createReplyDraftForEntry (ctx , w , latestEntryID , draft )
265+ return createReplyDraftForEntry (ctx , w , entries [len (entries )- 1 ].ID , draft )
279266}
280267
281268func createReplyDraftForEntry (ctx context.Context , w io.Writer , latestEntryID int64 , draft draftFormRequest ) error {
@@ -291,6 +278,10 @@ func createReplyDraftForEntry(ctx context.Context, w io.Writer, latestEntryID in
291278 if draft .Subject == "" {
292279 draft .Subject = replyForm .Request .Subject
293280 }
281+ draft = withReplyFormRecipients (draft , replyForm .Request )
282+ if len (draft .To ) == 0 && len (draft .CC ) == 0 && len (draft .BCC ) == 0 {
283+ return output .ErrUsage ("could not determine thread recipients" )
284+ }
294285
295286 values := draftValues (senderID , draft )
296287 resp , err := submitDraftForm (ctx , "POST" , fmt .Sprintf ("/entries/%d/replies" , latestEntryID ), values , replyForm .CSRFToken )
@@ -391,7 +382,7 @@ func draftValues(senderID int64, draft draftFormRequest) url.Values {
391382 values .Set ("acting_sender_id" , fmt .Sprintf ("%d" , senderID ))
392383 values .Set ("entry[status]" , "drafted" )
393384 values .Set ("message[subject]" , draft .Subject )
394- values .Set ("message[content]" , draft .Content )
385+ values .Set ("message[content]" , draftContentHTML ( draft .Content ) )
395386 for _ , to := range draft .To {
396387 values .Add ("entry[addressed][directly][]" , to )
397388 }
@@ -404,6 +395,40 @@ func draftValues(senderID int64, draft draftFormRequest) url.Values {
404395 return values
405396}
406397
398+ func withReplyFormRecipients (draft , replyForm draftFormRequest ) draftFormRequest {
399+ if len (draft .To ) > 0 || len (draft .CC ) > 0 || len (draft .BCC ) > 0 {
400+ return draft
401+ }
402+ draft .To = replyForm .To
403+ draft .CC = replyForm .CC
404+ draft .BCC = replyForm .BCC
405+ return draft
406+ }
407+
408+ func draftContentHTML (content string ) string {
409+ if looksLikeDraftHTML (content ) {
410+ return content
411+ }
412+
413+ content = strings .ReplaceAll (content , "\r \n " , "\n " )
414+ content = strings .ReplaceAll (content , "\r " , "\n " )
415+ lines := strings .Split (content , "\n " )
416+ for i , line := range lines {
417+ lines [i ] = html .EscapeString (line )
418+ }
419+ return "<div>" + strings .Join (lines , "<br>" ) + "</div>"
420+ }
421+
422+ func looksLikeDraftHTML (content string ) bool {
423+ trimmed := strings .TrimSpace (strings .ToLower (content ))
424+ return strings .HasPrefix (trimmed , "<div" ) ||
425+ strings .HasPrefix (trimmed , "<p" ) ||
426+ strings .HasPrefix (trimmed , "<ul" ) ||
427+ strings .HasPrefix (trimmed , "<ol" ) ||
428+ strings .HasPrefix (trimmed , "<blockquote" ) ||
429+ strings .Contains (trimmed , "<br" )
430+ }
431+
407432func submitDraftForm (ctx context.Context , method , path string , values url.Values , csrfToken string ) (draftResponse , error ) {
408433 if csrfToken != "" {
409434 values .Set ("authenticity_token" , csrfToken )
0 commit comments