@@ -453,6 +453,163 @@ func TestSignatureFileContentType_HTML(t *testing.T) {
453453 }
454454}
455455
456+ func TestAppendSignaturePlain (t * testing.T ) {
457+ tests := []struct {
458+ name string
459+ body string
460+ signature string
461+ want string
462+ }{
463+ {name : "normal case" , body : "Hello" , signature : "-- John" , want : "Hello\n \n --\n -- John" },
464+ {name : "empty signature" , body : "Hello" , signature : "" , want : "Hello" },
465+ {name : "whitespace-only signature" , body : "Hello" , signature : " " , want : "Hello" },
466+ {name : "empty body with signature" , body : "" , signature : "Sig" , want : "\n \n --\n Sig" },
467+ }
468+ for _ , tt := range tests {
469+ t .Run (tt .name , func (t * testing.T ) {
470+ got := appendSignaturePlain (tt .body , tt .signature )
471+ if got != tt .want {
472+ t .Errorf ("appendSignaturePlain(%q, %q)\n got: %q\n want: %q" , tt .body , tt .signature , got , tt .want )
473+ }
474+ })
475+ }
476+ }
477+
478+ func TestAppendSignatureHTML (t * testing.T ) {
479+ tests := []struct {
480+ name string
481+ body string
482+ signature string
483+ want string
484+ }{
485+ {
486+ name : "normal case" ,
487+ body : "<p>Hi</p>" ,
488+ signature : "<div>Sig</div>" ,
489+ want : "<p>Hi</p>\n \n " + `<div class="gmail_signature"><div>Sig</div></div>` ,
490+ },
491+ {name : "empty signature" , body : "<p>Hi</p>" , signature : "" , want : "<p>Hi</p>" },
492+ {name : "whitespace-only signature" , body : "<p>Hi</p>" , signature : " " , want : "<p>Hi</p>" },
493+ }
494+ for _ , tt := range tests {
495+ t .Run (tt .name , func (t * testing.T ) {
496+ got := appendSignatureHTML (tt .body , tt .signature )
497+ if got != tt .want {
498+ t .Errorf ("appendSignatureHTML(%q, %q)\n got: %q\n want: %q" , tt .body , tt .signature , got , tt .want )
499+ }
500+ })
501+ }
502+ }
503+
504+ func TestValidateSignatureFlags (t * testing.T ) {
505+ tests := []struct {
506+ name string
507+ signature bool
508+ signatureName string
509+ signatureFile string
510+ wantErr bool
511+ }{
512+ {name : "no flags set" , signature : false , signatureName : "" , signatureFile : "" , wantErr : false },
513+ {name : "only --signature" , signature : true , signatureName : "" , signatureFile : "" , wantErr : false },
514+ {name : "only --signature-name" , signature : false , signatureName : "alias@example.com" , signatureFile : "" , wantErr : false },
515+ {name : "only --signature-file" , signature : false , signatureName : "" , signatureFile : "/tmp/sig.html" , wantErr : false },
516+ {name : "--signature + --signature-name" , signature : true , signatureName : "alias@example.com" , signatureFile : "" , wantErr : true },
517+ {name : "--signature + --signature-file" , signature : true , signatureName : "" , signatureFile : "/tmp/sig.html" , wantErr : true },
518+ {name : "--signature-name + --signature-file" , signature : false , signatureName : "alias@example.com" , signatureFile : "/tmp/sig.html" , wantErr : true },
519+ {name : "all three" , signature : true , signatureName : "alias@example.com" , signatureFile : "/tmp/sig.html" , wantErr : true },
520+ }
521+ for _ , tt := range tests {
522+ t .Run (tt .name , func (t * testing.T ) {
523+ err := validateSignatureFlags (tt .signature , tt .signatureName , tt .signatureFile )
524+ if (err != nil ) != tt .wantErr {
525+ t .Errorf ("validateSignatureFlags(%v, %q, %q) error = %v, wantErr = %v" ,
526+ tt .signature , tt .signatureName , tt .signatureFile , err , tt .wantErr )
527+ }
528+ })
529+ }
530+ }
531+
532+ func TestGmailSendCmd_SignatureNameAlias (t * testing.T ) {
533+ origNew := newGmailService
534+ t .Cleanup (func () { newGmailService = origNew })
535+
536+ var gotRaw string
537+ var gotSendAsGetPath string
538+ srv := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
539+ path := strings .TrimPrefix (r .URL .Path , "/gmail/v1" )
540+ switch {
541+ case r .Method == http .MethodGet && strings .HasPrefix (path , "/users/me/settings/sendAs/" ):
542+ gotSendAsGetPath = path
543+ w .Header ().Set ("Content-Type" , "application/json" )
544+ _ = json .NewEncoder (w ).Encode (map [string ]any {
545+ "sendAsEmail" : "alias@example.com" ,
546+ "signature" : "<div>Alias Sig</div>" ,
547+ "verificationStatus" : "accepted" ,
548+ })
549+ return
550+ case r .Method == http .MethodPost && path == "/users/me/messages/send" :
551+ var payload struct {
552+ Raw string `json:"raw"`
553+ }
554+ if err := json .NewDecoder (r .Body ).Decode (& payload ); err != nil {
555+ t .Fatalf ("decode payload: %v" , err )
556+ }
557+ decoded , err := base64 .RawURLEncoding .DecodeString (payload .Raw )
558+ if err != nil {
559+ t .Fatalf ("decode raw: %v" , err )
560+ }
561+ gotRaw = string (decoded )
562+ w .Header ().Set ("Content-Type" , "application/json" )
563+ _ = json .NewEncoder (w ).Encode (map [string ]any {"id" : "m1" })
564+ return
565+ default :
566+ http .NotFound (w , r )
567+ return
568+ }
569+ }))
570+ defer srv .Close ()
571+
572+ svc , err := gmail .NewService (context .Background (),
573+ option .WithoutAuthentication (),
574+ option .WithHTTPClient (srv .Client ()),
575+ option .WithEndpoint (srv .URL + "/" ),
576+ )
577+ if err != nil {
578+ t .Fatalf ("NewService: %v" , err )
579+ }
580+ newGmailService = func (context.Context , string ) (* gmail.Service , error ) { return svc , nil }
581+
582+ u , err := ui .New (ui.Options {Stdout : io .Discard , Stderr : io .Discard , Color : "never" })
583+ if err != nil {
584+ t .Fatalf ("ui.New: %v" , err )
585+ }
586+ ctx := ui .WithUI (context .Background (), u )
587+
588+ cmd := & GmailSendCmd {
589+ To : "recipient@example.com" ,
590+ Subject : "Hello" ,
591+ Body : "Body" ,
592+ SignatureName : "alias@example.com" ,
593+ }
594+ if err := cmd .Run (ctx , & RootFlags {Account : "a@b.com" }); err != nil {
595+ t .Fatalf ("Run: %v" , err )
596+ }
597+
598+ // Verify the SendAs.Get call used alias@example.com, not the account email a@b.com.
599+ wantPath := "/users/me/settings/sendAs/alias@example.com"
600+ if gotSendAsGetPath != wantPath {
601+ t .Errorf ("expected SendAs.Get path %q, got %q" , wantPath , gotSendAsGetPath )
602+ }
603+
604+ if gotRaw == "" {
605+ t .Fatal ("expected raw message" )
606+ }
607+ // The signature HTML should be converted to plain text "Alias Sig" and appended.
608+ if ! strings .Contains (gotRaw , "Body\r \n \r \n --\r \n Alias Sig" ) {
609+ t .Errorf ("expected alias signature in plain body, got: %q" , gotRaw )
610+ }
611+ }
612+
456613func TestSignatureHTMLToPlain (t * testing.T ) {
457614 tests := []struct {
458615 name string
0 commit comments